on master help sign in
Added docs
commitcf88ceab8b3fa502da4f598e7d40735ef30ca923 authoriko <ilyakooo0@gmail.com> dateSun 18 Apr 2021, 14:38 (5 years ago) parent33ad45d
18 files changed+1273
.github/workflows/build_docs.yaml+63 .gitignore+1 docs/.vscode/settings.json+104 docs/bibl.bib+132 docs/default.nix+20 docs/en_pres/img/lsp.png docs/en_pres/img/nixpkgs.png docs/en_pres/pres.md+112 docs/en_pres/pres.pdf docs/nix/sources.json+26 docs/nix/sources.nix+171 docs/pres/img/lsp.png docs/pres/img/nixpkgs.png docs/pres/pres.md+213 docs/pres/pres.pdf docs/project_proposal.tex+131 docs/tech_spec.tex+288 tix.code-workspace+12
.github/workflows/build_docs.yamlnew file+63
@@ -0,0 +1,63 @@
1+name: Build docs
2+on:
3+ push:
4+ branches:
5+ - master
6+ pull_request:
7+ branches:
8+ - master
9+
10+jobs:
11+ linux:
12+ name: Build docs
13+ runs-on: ubuntu-latest
14+ defaults:
15+ run:
16+ working-directory: docs
17+ steps:
18+ - uses: actions/checkout@v1
19+ - uses: cachix/install-nix-action@v12
20+ - name: Create /nix/store
21+ run: |
22+ sudo rm -rf /nix/store
23+ sudo mkdir -p /nix/store
24+ sudo chown --verbose "$USER:" /nix/store
25+ - name: Cache
26+ uses: actions/cache@v2
27+ with:
28+ path: |
29+ /nix/store
30+ key: ${{ runner.os }}-nix
31+ - name: Build
32+ id: build
33+ run: |
34+ mkdir res
35+ for f in $(nix-build)
36+ do
37+ cp $f/*.pdf res
38+ done
39+ - uses: actions/upload-artifact@v2
40+ with:
41+ name: docs
42+ path: res/*.pdf
43+ - uses: "marvinpinto/action-automatic-releases@latest"
44+ with:
45+ repo_token: "${{ secrets.GITHUB_TOKEN }}"
46+ automatic_release_tag: "docs_latest"
47+ # prerelease: true
48+ title: "Docs"
49+ files: |
50+ res/*.pdf
51+ # - name: Create Release
52+ # uses: actions/create-release@v1
53+ # env:
54+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55+ # with:
56+ # tag_name: ${{ github.ref }}
57+ # release_name: Release ${{ github.ref }}
58+ # body: |
59+ # Changes in this Release
60+ # - First Change
61+ # - Second Change
62+ # draft: false
63+ # prerelease: false
.gitignore+1
@@ -1,3 +1,4 @@
11.stack-work/
22*~
33tix.cabal
4+docs/result*
docs/.vscode/settings.jsonnew file+104
@@ -0,0 +1,104 @@
1+{
2+ "latex-workshop.latex.outDir": "%TMPDIR%",
3+ "editor.wordWrap": "on",
4+ "grammarly.userWords": [
5+ "nixpkgs",
6+ "typechecked",
7+ "typechecking"
8+ ],
9+ "nixEnvSelector.nixFile": "${workspaceRoot}/default.nix",
10+ "latex-workshop.latex.tools": [
11+ {
12+ "name": "latexmk",
13+ "command": "latexmk",
14+ "args": [
15+ "-synctex=1",
16+ "-interaction=nonstopmode",
17+ "-file-line-error",
18+ "-pdf",
19+ "-outdir=%OUTDIR%",
20+ "%DOC%"
21+ ],
22+ "env": {}
23+ },
24+ {
25+ "name": "lualatexmk",
26+ "command": "latexmk",
27+ "args": [
28+ "-synctex=1",
29+ "-interaction=nonstopmode",
30+ "-file-line-error",
31+ "-lualatex",
32+ "-outdir=%OUTDIR%",
33+ "%DOC%"
34+ ],
35+ "env": {}
36+ },
37+ {
38+ "name": "latexmk_rconly",
39+ "command": "latexmk",
40+ "args": [
41+ "%DOC%"
42+ ],
43+ "env": {}
44+ },
45+ {
46+ "name": "pdflatex",
47+ "command": "pdflatex",
48+ "args": [
49+ "-synctex=1",
50+ "-interaction=nonstopmode",
51+ "-file-line-error",
52+ "-output-directory=%TMPDIR%",
53+ "%DOC%"
54+ ],
55+ "env": {}
56+ },
57+ {
58+ "name": "bibtex",
59+ "command": "bibtex",
60+ "args": [
61+ "%DOCFILE%"
62+ ],
63+ "env": {}
64+ },
65+ {
66+ "name": "rnw2tex",
67+ "command": "Rscript",
68+ "args": [
69+ "-e",
70+ "knitr::opts_knit$set(concordance = TRUE); knitr::knit('%DOCFILE_EXT%')"
71+ ],
72+ "env": {}
73+ },
74+ {
75+ "name": "jnw2tex",
76+ "command": "julia",
77+ "args": [
78+ "-e",
79+ "using Weave; weave(\"%DOC_EXT%\", doctype=\"tex\")"
80+ ],
81+ "env": {}
82+ },
83+ {
84+ "name": "jnw2texmintex",
85+ "command": "julia",
86+ "args": [
87+ "-e",
88+ "using Weave; weave(\"%DOC_EXT%\", doctype=\"texminted\")"
89+ ],
90+ "env": {}
91+ },
92+ {
93+ "name": "tectonic",
94+ "command": "tectonic",
95+ "args": [
96+ "--synctex",
97+ "--keep-logs",
98+ "%DOC%.tex"
99+ ],
100+ "env": {}
101+ }
102+ ],
103+ "latex-workshop.latex.recipe.default": "latexmk ๐Ÿ”ƒ"
104+}
docs/bibl.bibnew file+132
@@ -0,0 +1,132 @@
1+%% This BibTeX bibliography file was created using BibDesk.
2+%% https://bibdesk.sourceforge.io/
3+
4+%% Created for Ilya at 2021-02-23 23:13:31 +0300
5+
6+
7+%% Saved with string encoding Unicode (UTF-8)
8+
9+
10+
11+@inproceedings{hughes1995design,
12+ author = {Hughes, John},
13+ booktitle = {International School on Advanced Functional Programming},
14+ date-added = {2021-02-23 23:13:30 +0300},
15+ date-modified = {2021-02-23 23:13:30 +0300},
16+ organization = {Springer},
17+ pages = {53--96},
18+ title = {The design of a pretty-printing library},
19+ year = {1995}}
20+
21+@inproceedings{orchard2010haskell,
22+ author = {Orchard, Dominic and Schrijvers, Tom},
23+ booktitle = {International Symposium on Functional and Logic Programming},
24+ date-added = {2021-02-23 23:13:12 +0300},
25+ date-modified = {2021-02-23 23:13:12 +0300},
26+ organization = {Springer},
27+ pages = {56--71},
28+ title = {Haskell type constraints unleashed},
29+ year = {2010}}
30+
31+@inproceedings{serrano2016type,
32+ author = {Serrano, Alejandro and Hage, Jurriaan},
33+ booktitle = {European Symposium on Programming},
34+ date-added = {2021-02-23 23:12:58 +0300},
35+ date-modified = {2021-02-23 23:12:58 +0300},
36+ organization = {Springer},
37+ pages = {672--698},
38+ title = {Type error diagnosis for embedded DSLs by Two-Stage specialized type rules},
39+ year = {2016}}
40+
41+@inproceedings{jones1999typing,
42+ author = {Jones, Mark P},
43+ booktitle = {Haskell workshop},
44+ date-added = {2021-02-23 23:12:45 +0300},
45+ date-modified = {2021-02-23 23:12:45 +0300},
46+ title = {Typing haskell in haskell},
47+ volume = {7},
48+ year = {1999}}
49+
50+@article{leijen2005extensible,
51+ author = {Leijen, Daan},
52+ date-added = {2021-02-23 23:12:32 +0300},
53+ date-modified = {2021-02-23 23:12:32 +0300},
54+ journal = {Trends in Functional Programming},
55+ pages = {179--194},
56+ title = {Extensible records with scoped labels.},
57+ volume = {6},
58+ year = {2005}}
59+
60+@article{morris2019abstracting,
61+ author = {Morris, J Garrett and McKinna, James},
62+ date-added = {2021-02-23 23:12:00 +0300},
63+ date-modified = {2021-02-23 23:12:00 +0300},
64+ journal = {Proceedings of the ACM on Programming Languages},
65+ number = {POPL},
66+ pages = {1--28},
67+ publisher = {ACM New York, NY, USA},
68+ title = {Abstracting extensible data types: or, rows by any other name},
69+ volume = {3},
70+ year = {2019}}
71+
72+@article{jones2005practical,
73+ author = {Jones, Simon Peyton and Vytiniotis, Dimitrios and Weirich, Stephanie and Shields, Mark},
74+ date-added = {2021-02-23 23:11:33 +0300},
75+ date-modified = {2021-02-23 23:11:33 +0300},
76+ journal = {Journal of functional programming},
77+ title = {Practical type inference for arbitrary-rank types},
78+ volume = {17},
79+ year = {2005}}
80+
81+@article{wadler2003prettier,
82+ author = {Wadler, Philip},
83+ date-added = {2021-02-23 23:11:11 +0300},
84+ date-modified = {2021-02-23 23:11:11 +0300},
85+ journal = {The Fun of Programming, Cornerstones of Computing},
86+ pages = {223--243},
87+ publisher = {Citeseer},
88+ title = {A prettier printer},
89+ year = {2003}}
90+
91+@article{mitchell2012shake,
92+ author = {Mitchell, Neil},
93+ date-added = {2021-02-23 23:10:56 +0300},
94+ date-modified = {2021-02-23 23:10:56 +0300},
95+ journal = {ACM SIGPLAN Notices},
96+ number = {9},
97+ pages = {55--66},
98+ publisher = {ACM New York, NY, USA},
99+ title = {Shake before building: Replacing make with Haskell},
100+ volume = {47},
101+ year = {2012}}
102+
103+@misc{vaughanproof,
104+ author = {Vaughan, Jeff},
105+ date-added = {2021-02-23 23:10:39 +0300},
106+ date-modified = {2021-02-23 23:10:39 +0300},
107+ title = {A proof of correctness for the Hindley-Milner type inference algorithm}}
108+
109+@inproceedings{damas1982principal,
110+ author = {Damas, Luis and Milner, Robin},
111+ booktitle = {Proceedings of the 9th ACM SIGPLAN-SIGACT symposium on Principles of programming languages},
112+ date-added = {2021-02-23 23:10:11 +0300},
113+ date-modified = {2021-02-23 23:10:11 +0300},
114+ pages = {207--212},
115+ title = {Principal type-schemes for functional programs},
116+ year = {1982}}
117+
118+@article{ben2009yaml,
119+ author = {Ben-Kiki, Oren and Evans, Clark and Ingerson, Brian},
120+ date-added = {2021-02-23 23:09:50 +0300},
121+ date-modified = {2021-02-23 23:09:50 +0300},
122+ journal = {Working Draft 2008-05},
123+ title = {Yaml ain't markup language (yaml{\texttrademark}) version 1.1},
124+ volume = {11},
125+ year = {2009}}
126+
127+@inproceedings{dolstra2008nixos,
128+ author = {Dolstra, Eelco and L{\"o}h, Andres},
129+ booktitle = {Proceedings of the 13th ACM SIGPLAN international conference on Functional programming},
130+ pages = {367--378},
131+ title = {NixOS: A purely functional Linux distribution},
132+ year = {2008}}
docs/default.nixnew file+20
@@ -0,0 +1,20 @@
1+{ sources ? import nix/sources.nix }:
2+let pkgs = import sources.nixpkgs { };
3+in
4+map
5+ (file: pkgs.texFunctions.runLaTeX {
6+ rootFile = file;
7+ # , generatePDF ? true # generate PDF, not DVI
8+ # , generatePS ? false # generate PS in addition to DVI
9+ # , extraFiles ? [ ]
10+ # , compressBlanksInIndex ? true
11+ # , packages ? [ ]
12+ texPackages = {
13+ inherit (pkgs.texlive) scheme-full;
14+ };
15+ # , copySources ? false
16+ })
17+ [
18+ ./tech_spec.tex
19+ ./project_proposal.tex
20+ ]
docs/en_pres/img/lsp.pngnew file

Binary file not shown.

docs/en_pres/img/nixpkgs.pngnew file

Binary file not shown.

docs/en_pres/pres.mdnew file+112
@@ -0,0 +1,112 @@
1+build-lists: false
2+slidenumbers: true
3+
4+[.header: alignment(center), Avenir Next]
5+
6+<br>
7+<br>
8+
9+## Language Server for the Nix Expression Language
10+
11+<br>
12+<br>
13+
14+_Author:_ Kostyuchenko Ilya
15+
16+---
17+
18+> Nix is a powerful package manager that makes package management reliable and reproducible.
19+-- [nixos.org](https://nixos.org)
20+
21+---
22+
23+# Nix
24+
25+- Package manager
26+- Build system*
27+- Ad hoc development environments
28+- Easy (cross-community) dependency management
29+- Reproducible builds
30+- *And much more: NixOS, NixOps, Build Caching, Docker ...*
31+
32+---
33+
34+# Nix Expression Language
35+
36+```nix
37+let pkgs = import ./nixpkgs {};
38+in derivation {
39+ name = "simple";
40+ builder = "${pkgs.bash}/bin/bash";
41+ args = [ ./simple_builder.sh ];
42+ gcc = pkgs.gcc;
43+ coreutils = pkgs.coreutils;
44+ src = ./simple.c;
45+ system = builtins.currentSystem;
46+}
47+```
48+
49+---
50+
51+[.build-lists: true]
52+
53+# Project scope
54+
55+1. Develop a type system (and type checker)
56+2. Develop a Language Server
57+
58+---
59+
60+# Language Server Protocol
61+
62+![inline](img/lsp.png)
63+
64+---
65+
66+# The Nix Ecosystem
67+
68+The central repository contains more than 60000 packages.
69+
70+![right fit](img/nixpkgs.png)
71+
72+---
73+
74+# Existing approaches
75+
76+Type systems for functional languages is an actively researched field.
77+
78+The Hindleyโ€“Milner type system_[1]_ is a simple, but well-studied type system for a very simple language. It is fully decidable, does not require annotations. It is the basis for many real-world type systems.
79+
80+---
81+
82+# Methods and algorithms
83+
84+The type system will be heavily influenced by the Hindleyโ€“Milner_[1]_ type system.
85+
86+The type system will implement arbitrary-ranked polymorphism_[3]_ with deep instantiation to disambiguate types in existing untyped code.
87+
88+The type system will allow the user to influence type checking by providing explicit type annotations._[4]_
89+
90+---
91+
92+# Methods and algorithms
93+
94+The system will use the Shake build system to manage dependencies and caches._[3]_
95+
96+---
97+
98+# Expected results
99+
100+1. An executable of the Nix expression language server with an integrated type checker.
101+2. A suite of automated tests to check some of the language server functionality.
102+
103+---
104+
105+[.text: text-scale(0.7)]
106+
107+# References
108+
109+1. Damas L., Milner R. Principal type-schemes for functional programs //Proceedings of the 9th ACM SIGPLAN-SIGACT symposium on Principles of programming languages. โ€“ 1982. โ€“ ะก. 207-212.
110+2. Mitchell N. Shake before building: replacing make with haskell //ACM SIGPLAN Notices. โ€“ 2012. โ€“ ะข. 47. โ€“ โ„–. 9. โ€“ ะก. 55-66.
111+3. Jones S. P. et al. Practical type inference for arbitrary-rank types //Journal of functional programming. โ€“ 2007. โ€“ ะข. 17. โ€“ โ„–. 1. โ€“ ะก. 1-82. MLA
112+4. Stuckey P. J., Sulzmann M., Wazny J. Improved inference for checking type annotations //arXiv preprint cs/0507036. โ€“ 2005. MLA
docs/en_pres/pres.pdfnew file

Binary file not shown.

docs/nix/sources.jsonnew file+26
@@ -0,0 +1,26 @@
1+{
2+ "niv": {
3+ "branch": "master",
4+ "description": "Easy dependency management for Nix projects",
5+ "homepage": "https://github.com/nmattia/niv",
6+ "owner": "nmattia",
7+ "repo": "niv",
8+ "rev": "af958e8057f345ee1aca714c1247ef3ba1c15f5e",
9+ "sha256": "1qjavxabbrsh73yck5dcq8jggvh3r2jkbr6b5nlz5d9yrqm9255n",
10+ "type": "tarball",
11+ "url": "https://github.com/nmattia/niv/archive/af958e8057f345ee1aca714c1247ef3ba1c15f5e.tar.gz",
12+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13+ },
14+ "nixpkgs": {
15+ "branch": "release-20.09",
16+ "description": "Nix Packages collection",
17+ "homepage": "",
18+ "owner": "NixOS",
19+ "repo": "nixpkgs",
20+ "rev": "68e1d0bf8d5066139105ad73d0d65845fb4fc953",
21+ "sha256": "0licfz0wgjkpkrpyzv1cv35f83grxndsr9vb34pidgn3zdjl4nf2",
22+ "type": "tarball",
23+ "url": "https://github.com/NixOS/nixpkgs/archive/68e1d0bf8d5066139105ad73d0d65845fb4fc953.tar.gz",
24+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
25+ }
26+}
docs/nix/sources.nixnew file+171
@@ -0,0 +1,171 @@
1+# This file has been generated by Niv.
2+
3+let
4+
5+ #
6+ # The fetchers. fetch_<type> fetches specs of type <type>.
7+ #
8+
9+ fetch_file = pkgs: name: spec:
10+ let
11+ name' = sanitizeName name + "-src";
12+ in
13+ if spec.builtin or true then
14+ builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15+ else
16+ pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17+
18+ fetch_tarball = pkgs: name: spec:
19+ let
20+ name' = sanitizeName name + "-src";
21+ in
22+ if spec.builtin or true then
23+ builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24+ else
25+ pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26+
27+ fetch_git = name: spec:
28+ let
29+ ref =
30+ if spec ? ref then spec.ref else
31+ if spec ? branch then "refs/heads/${spec.branch}" else
32+ if spec ? tag then "refs/tags/${spec.tag}" else
33+ abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
34+ in
35+ builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
36+
37+ fetch_local = spec: spec.path;
38+
39+ fetch_builtin-tarball = name: throw
40+ ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
41+ $ niv modify ${name} -a type=tarball -a builtin=true'';
42+
43+ fetch_builtin-url = name: throw
44+ ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
45+ $ niv modify ${name} -a type=file -a builtin=true'';
46+
47+ #
48+ # Various helpers
49+ #
50+
51+ # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
52+ sanitizeName = name:
53+ (
54+ concatMapStrings (s: if builtins.isList s then "-" else s)
55+ (
56+ builtins.split "[^[:alnum:]+._?=-]+"
57+ ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
58+ )
59+ );
60+
61+ # The set of packages used when specs are fetched using non-builtins.
62+ mkPkgs = sources: system:
63+ let
64+ sourcesNixpkgs =
65+ import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
66+ hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
67+ hasThisAsNixpkgsPath = <nixpkgs> == ./.;
68+ in
69+ if builtins.hasAttr "nixpkgs" sources
70+ then sourcesNixpkgs
71+ else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
72+ import <nixpkgs> {}
73+ else
74+ abort
75+ ''
76+ Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
77+ add a package called "nixpkgs" to your sources.json.
78+ '';
79+
80+ # The actual fetching function.
81+ fetch = pkgs: name: spec:
82+
83+ if ! builtins.hasAttr "type" spec then
84+ abort "ERROR: niv spec ${name} does not have a 'type' attribute"
85+ else if spec.type == "file" then fetch_file pkgs name spec
86+ else if spec.type == "tarball" then fetch_tarball pkgs name spec
87+ else if spec.type == "git" then fetch_git name spec
88+ else if spec.type == "local" then fetch_local spec
89+ else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
90+ else if spec.type == "builtin-url" then fetch_builtin-url name
91+ else
92+ abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
93+
94+ # If the environment variable NIV_OVERRIDE_${name} is set, then use
95+ # the path directly as opposed to the fetched source.
96+ replace = name: drv:
97+ let
98+ saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
99+ ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
100+ in
101+ if ersatz == "" then drv else ersatz;
102+
103+ # Ports of functions for older nix versions
104+
105+ # a Nix version of mapAttrs if the built-in doesn't exist
106+ mapAttrs = builtins.mapAttrs or (
107+ f: set: with builtins;
108+ listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
109+ );
110+
111+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
112+ range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
113+
114+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
115+ stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
116+
117+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
118+ stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
119+ concatMapStrings = f: list: concatStrings (map f list);
120+ concatStrings = builtins.concatStringsSep "";
121+
122+ # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
123+ optionalAttrs = cond: as: if cond then as else {};
124+
125+ # fetchTarball version that is compatible between all the versions of Nix
126+ builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
127+ let
128+ inherit (builtins) lessThan nixVersion fetchTarball;
129+ in
130+ if lessThan nixVersion "1.12" then
131+ fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
132+ else
133+ fetchTarball attrs;
134+
135+ # fetchurl version that is compatible between all the versions of Nix
136+ builtins_fetchurl = { url, name ? null, sha256 }@attrs:
137+ let
138+ inherit (builtins) lessThan nixVersion fetchurl;
139+ in
140+ if lessThan nixVersion "1.12" then
141+ fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
142+ else
143+ fetchurl attrs;
144+
145+ # Create the final "sources" from the config
146+ mkSources = config:
147+ mapAttrs (
148+ name: spec:
149+ if builtins.hasAttr "outPath" spec
150+ then abort
151+ "The values in sources.json should not have an 'outPath' attribute"
152+ else
153+ spec // { outPath = replace name (fetch config.pkgs name spec); }
154+ ) config.sources;
155+
156+ # The "config" used by the fetchers
157+ mkConfig =
158+ { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
159+ , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
160+ , system ? builtins.currentSystem
161+ , pkgs ? mkPkgs sources system
162+ }: rec {
163+ # The sources, i.e. the attribute set of spec name to spec
164+ inherit sources;
165+
166+ # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
167+ inherit pkgs;
168+ };
169+
170+in
171+mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
docs/pres/img/lsp.pngnew file

Binary file not shown.

docs/pres/img/nixpkgs.pngnew file

Binary file not shown.

docs/pres/pres.mdnew file+213
@@ -0,0 +1,213 @@
1+build-lists: true
2+slidenumbers: true
3+
4+[.header: alignment(center), Avenir Next]
5+
6+## ะฏะทั‹ะบะพะฒะพะน ัะตั€ะฒะตั€ ะดะปั Nix Expression Language
7+
8+## Language Server for the Nix Expression Language
9+
10+<br>
11+
12+_ะะฒั‚ะพั€:_ ะšะพัั‚ัŽั‡ะตะฝะบะพ ะ˜ะปัŒั ะ˜ะณะพั€ะตะฒะธั‡
13+
14+_ะ ัƒะบะพะฒะพะดะธั‚ะตะปัŒ:_ ะšัƒะปัะผะธะฝ ะ’ะธะบั‚ะพั€ ะ’ัั‡ะตัะปะฐะฒะพะฒะธั‡, ะ”ะพั†ะตะฝั‚, ะฑะฐะทะพะฒะฐั ะบะฐั„ะตะดั€ะฐ "ะกะธัั‚ะตะผะฝะพะต ะฟั€ะพะณั€ะฐะผะผะธั€ะพะฒะฐะฝะธะต"
15+
16+---
17+
18+> Nix is a powerful package manager that makes package management reliable and reproducible.
19+-- [nixos.org](https://nixos.org)
20+
21+---
22+
23+# Nix
24+
25+- Package manager
26+- Build system*
27+- Ad hoc development environments
28+- Easy (cross-community) dependency management
29+- Reproducible builds
30+- *And much more: NixOS, NixOps, Build Caching, Docker ...*
31+
32+---
33+
34+# Nix Expression Language
35+
36+- Purely functional
37+ - No shared mutable state
38+ - Easy to reason about
39+ - Easy reuse
40+- Lazy
41+- Strict, but not static typing
42+
43+---
44+
45+# Nix Expression Language
46+
47+```nix
48+let pkgs = import ./nixpkgs {};
49+in derivation {
50+ name = "simple";
51+ builder = "${pkgs.bash}/bin/bash";
52+ args = [ ./simple_builder.sh ];
53+ gcc = pkgs.gcc;
54+ coreutils = pkgs.coreutils;
55+ src = ./simple.c;
56+ system = builtins.currentSystem;
57+}
58+```
59+
60+---
61+
62+# Language Server Protocol
63+
64+The Language Server Protocol (LSP) defines the protocol used between an editor or IDE and a language server that provides language features like autocomplete, go to definition, find all references etc.
65+
66+---
67+
68+# Language Server Protocol
69+
70+![inline](img/lsp.png)
71+
72+---
73+
74+[.text: text-scale(0.85)]
75+
76+# Terms and definitions
77+
78+**Type system** โ€“ a logical system comprising a set of rules that assigns a property called a type to the various constructs of a computer program
79+
80+**Type checking** โ€“ the process of verifying and enforcing the constraints of types.
81+
82+**Hindleyโ€“Milner type system** โ€“ a classical type system for the lambda calculus with parametric polymorphism.
83+
84+**Language Server** โ€“ a service for analyzing code in a specific language which can be used in many code editors.
85+
86+---
87+
88+# Relevance
89+
90+The Nix ecosystem is slowly becoming popular.
91+
92+The central repository contains more than 60000 packages.
93+
94+There is a need to make writing Nix expressions less error-prone.
95+
96+![right fit](img/nixpkgs.png)
97+
98+---
99+
100+# The goal
101+
102+1. Develop a type system for the existing Nix expression language
103+2. Develop a type checker for the type system
104+3. Develop a Language server for the Nix expression language integrating the type checker
105+
106+---
107+
108+# Existing approaches
109+
110+Type systems for functional languages is an actively researched field.
111+
112+The Hindleyโ€“Milner type system_[1]_ is a simple, but well-studied type system for a very simple language. It is fully decidable, does not require annotations. It is the basis for many real-world type systems.
113+
114+---
115+
116+# Existing solutions
117+
118+## Type systems
119+
120+- github.com/regnat/ptyx โ€“ Abandoned and incomplete.
121+- github.com/regnat/tix โ€“ An older version of ptyx. Abandoned, terribly incomplete.
122+- github.com/haskell-nix/hnix โ€“ has a module with a type checker. Is very experimental and is not used.
123+
124+---
125+
126+# Existing solutions
127+
128+## Language servers
129+
130+- github.com/nix-community/rnix-lsp/ โ€“ Basic goto and error reporting. No type system, extremely simple.
131+- github.com/nix-community/vscode-nix-ide โ€“ Basic instantiation error reporting. (`nix-instantiate`)
132+
133+---
134+
135+# Functional requirements
136+
137+- The system should perform type checking for expression.
138+
139+- The system should analyze conditional statements where the condition consists only of type checks and boolean operators built into the Nix expression language.
140+
141+- The system should analyze the types and presence of attributes in attribute sets.
142+
143+- The system should report encountered typechecking.
144+
145+---
146+
147+# Functional requirements
148+
149+- The system should provide the location of definitions for all locally used terms .
150+
151+- The system should report the use of undefined terms through means defined by the Language Server Protocol.
152+
153+- The system should report the types of requested expressions through means defined by the Language Server Protocol.
154+
155+---
156+
157+# Functional requirements
158+
159+- The system should provide code completions suggestions from the variables currently in scope and expressions built into the language.
160+
161+- The system should provide a way for the programmer to explicitly annotate types of expressions which will influence type checking.
162+
163+---
164+
165+# Methods and algorithms
166+
167+The type system will be heavily influenced by the Hindleyโ€“Milner_[1]_ type system.
168+
169+The type system will implement arbitrary-ranked polymorphism_[3]_ with deep instantiation to disambiguate them in existing untyped code.
170+
171+The type system will allow the user to influence type checking by providing explicit type annotations._[4]_
172+
173+---
174+
175+# Methods and algorithms
176+
177+The system will use the Shake build system to manage dependencies and caches._[3]_
178+
179+---
180+
181+# Used tools
182+
183+1. Haskell
184+2. Nix
185+3. Visual Studio Code
186+4. Haskell Language Server
187+5. Haskell Stack
188+
189+---
190+
191+# Used libraries
192+
193+1. hnix โ€“ Nix expression language parsing, will need to be forked
194+2. shake
195+3. acts โ€“ semigroup actions
196+
197+---
198+
199+# Expected results
200+
201+1. An executable of the Nix expression language server with an integrated type checker.
202+2. A suite of automated tests to check some of the language server functionality.
203+
204+---
205+
206+[.text: text-scale(0.7)]
207+
208+# References
209+
210+1. Damas L., Milner R. Principal type-schemes for functional programs //Proceedings of the 9th ACM SIGPLAN-SIGACT symposium on Principles of programming languages. โ€“ 1982. โ€“ ะก. 207-212.
211+2. Mitchell N. Shake before building: replacing make with haskell //ACM SIGPLAN Notices. โ€“ 2012. โ€“ ะข. 47. โ€“ โ„–. 9. โ€“ ะก. 55-66.
212+3. Jones S. P. et al. Practical type inference for arbitrary-rank types //Journal of functional programming. โ€“ 2007. โ€“ ะข. 17. โ€“ โ„–. 1. โ€“ ะก. 1-82. MLA
213+4. Stuckey P. J., Sulzmann M., Wazny J. Improved inference for checking type annotations //arXiv preprint cs/0507036. โ€“ 2005. MLA
docs/pres/pres.pdfnew file

Binary file not shown.

docs/project_proposal.texnew file+131
@@ -0,0 +1,131 @@
1+\documentclass[a4paper,conference]{IEEEtran}
2+
3+\usepackage{xcolor}
4+\usepackage[hidelinks]{hyperref}
5+\usepackage{url}
6+\usepackage[main=english]{babel}
7+% \usepackage[T1]{fontenc}
8+% \usepackage[utf8]{inputenc} %support umlauts in the input
9+
10+\title{Language Server for the Nix Expression Language}
11+
12+\author{
13+ \IEEEauthorblockN{Kostyuchenko Ilya}
14+ \IEEEauthorblockA{
15+ Faculty of Computer Science,\\
16+ Higher School of Economics,\\
17+ Moscow, Russia
18+ }
19+}
20+
21+\begin{document}
22+\maketitle
23+
24+\begin{abstract}
25+ Configuring and building even the most straightforward software projects is often not simple -- it requires downloading and installing copious amounts of prerequisite software. This often makes reproducing builds of a project on different machines problematic. The Nix package manager aims to address this problem by providing a unified language for describing software packages in a purely functional way. This language is called the Nix Expression Language. Since all of the complexity of software configuration needs to be expressed in the Nix Expression Language, the expressions themselves often become quite complicated, making it difficult to understand and extend existing expressions without introducing errors. A widespread tool for easing the understandability and correctness of expressions in other languages is static type checking. This paper will explore the techniques that can be used to add static type checking to the Nix Expression Language. We will also investigate making development even more comfortable with the help of the Language Server Protocol.
26+\end{abstract}
27+
28+\begin{IEEEkeywords}
29+ programming languages, type systems, type inference, language server protocol, Nix Expression Language, build systems
30+\end{IEEEkeywords}
31+
32+\section{Introduction}
33+
34+Today developing software is riddled with large amounts of complexity -- newer software is built on top of older software, dragging the whole stack below as dependencies. As a result, building software requires a large number of dependencies to be preinstalled. Modern build systems like Gradle\footnote{\url{https://gradle.org}}, Maven\footnote{\url{https://maven.apache.org}}, and Stack\footnote{\url{https://docs.haskellstack.org/en/stable/README/}} try to mitigate the issue by automatically downloading and installing the required dependencies. However, in most cases, such tools can only manage language-level dependencies, requiring the user to install additional libraries and tools manually.
35+
36+Such manual dependency management leads to several problems. Firstly, when a user wants to work on a project he has not encountered before, he will have to install the required dependencies, leading to additional tedious work. Furthermore, the required versions of project dependencies might conflict with the versions that another project requires. The user will have to manually switch the versions of executables and libraries when switching between projects.
37+
38+Secondly, manual dependency management impedes the reproducibility of the project builds -- building the same project on multiple machines will, in all likelihood, produce different results since the machines will likely differ in many ways that impact the build, such as having slightly different versions\footnote{``Version'' here refers to actual variations on the bit level, and not just version numbers.} of libraries and executables.
39+
40+Nix~\cite{dolstra2008nixos} attempts to solve the problems mentioned above by describing software project builds in a generic and language-agnostic way. Furthermore, the resulting descriptions define the build process in a complete and deterministic way -- everything that impacts the build in any way needs to be explicitly defined, even system-level libraries are reproducible on the bit level.
41+
42+Defining the build process in such a detailed manner is not easy. While most build systems define project builds with static configurations using formats such as YAML~\cite{ben2009yaml}, Nix employs a fully-fledged programming language as its configuration language. This programming language is called the Nix Expression Language\footnote{\url{https://nixos.wiki/wiki/Nix_Expression_Language}}.
43+
44+\section{Nix Expression Language}
45+
46+Nix Expression Language is a dynamic, lazy, purely functional programming language. The purely functional nature of the language aids in build reproducibility guarantees that Nix aims to provide.
47+
48+The fact that the Nix configuration language is a programming language certainly helps manage the complexities\footnote{The sheer amount of configuration required is itself large enough to be problematic.} defining \emph{everything} involved in building a software project. Even so, the dynamic nature of the language often makes it challenging to understand and reuse existing code.
49+
50+Refactoring existing code is also tricky since the generated expressions are only really checked for correctness\footnote{Here, ``correctness'' is used to mean the absence of evaluation-time errors.} at their evaluation time, and the evaluation time of expressions is difficult to predict due to the lazy nature of the language.
51+
52+\section{Static type checking}
53+
54+Static type checking is the process of analyzing the types of expressions and detecting type errors in programs without evaluating them.
55+
56+Even though static type checking in most mainstream programming languages does not influence the semantics of the programs, it is nonetheless widely used. This is an indication of the usefulness of static type checking during development. Type checking helps detect likely ``incorrect'' programs without evaluating them (very helpful during refactoring), and aids in understanding existing code since types often expose some semantics of expressions (this is especially true for purely functional programs).
57+
58+The Nix Expression Language does not currently support static type checking of any kind. Of course, retrofitting a static type checker onto an existing dynamic programming language will reject programs that will not produce errors at runtime. However, this is still a goal worth pursuing because even with all of the situations when the type checker produces false negatives, inferring types for existing expressions, as mentioned above, will aid in understanding existing code and surface potentially problematic areas of code to the developer.
59+
60+\section{Type System Approach}
61+
62+There has been much research done in the field of type systems for functional programming languages. The most notable contribution was the introduction of the Damas-Milner\footnote{The Damas-Milner type system is sometimes referred to as the Hindleyโ€“Milner type system.} type system and the W inference algorithm~\cite{damas1982principal}, which was later proven to be sound and complete~\cite{vaughanproof}.
63+
64+The Damas-Milner type system is a type system for lambda calculus with parametric polymorphism. The most notable property of the Damas-Milner type system is the proven ability of the W algorithm to infer the most general types without any user-provided type annotations.
65+
66+While the Damas-Milner describes a simple language, it is robust enough to be used as the basis for more advanced type systems such as the one used in the Haskell programming language~\cite{jones1999typing}, which extends the Damas-Milner type system in many ways which break the excellent properties it provides but remains extremely useful in practice.
67+
68+Since the Nix Expression Language is a relatively simple functional programming language, extending the Damas-Milner type system and algorithms to fit the language will be the approach we take as the tried and true method.
69+
70+\section{Type Checker Error Handling}
71+
72+Due to the inevitable presence of false negatives during type checking, for the type checker to be useful enough to be worth implementing, the algorithm should gracefully recover after encountering expressions that it deems to be ``wrong''.
73+
74+Since the interpreter of the programs will not be related to the developed type checker in any way, the type checker can not influence the semantics of the programs. This fact can be used to implement the following failure recovery heuristic: when the type checker encounters an expression that yields type checking errors, the errors are collected to be displayed to the user, and the expression is given the least general type possible such that it does not yield type errors.
75+
76+This is, in general, always possible since any syntactically valid expression will be correct with respect to types if every subexpression is assigned the polymorphic type:
77+
78+\begin{equation}
79+ \forall \alpha. \alpha
80+\end{equation}
81+
82+In some cases, this approach will likely yield too little information to be useful, but it seems like a reasonable solution.
83+
84+\section{Improving Type Checker Error Reporting}
85+
86+The original W inference algorithm is a single-stage inference algorithm, meaning that it attempts to satisfy type constraints as soon as it encounters them. A consequence of this is that errors are reported as soon as they are encountered. Often, the information available about the program at the time the error had occurred is very limited due to not all of the program being processed. This leads to poor error reporting.
87+
88+In contrast to the single-stage algorithm, the two-stage algorithm~\cite{jones2005practical,serrano2016type} collects the type constraints as the first stage of type checking and solves the collected constraints as a second step. This leads to most errors occurring during the second stage when all available type information has already been collected. As a result, better type errors are produced. This is the preferable approach for our goals.
89+
90+\section{Row-Polymorphism}
91+
92+One of the language-level constructs in the Nix Expression Language is the ``attribute set'' which can be thought of as a first-class hashmap with strings as keys. In combination with the dynamic nature of the language, these ``attribute sets'' have the semantics of row-polymorphic records.
93+
94+There has been some research conducted in the field of type systems with row-polymorphic records~\cite{morris2019abstracting,leijen2005extensible}. The approach that should be taken in developing a static type checker for the Nix Expression Language is describing row-polymorphic attribute sets with a construct similar\footnote{The way it should be displayed to the user will be distinct, since, unlike in Haskell, the Nix Expression Language does not have constraints as a language construct.} to Haskell constraints~\cite{orchard2010haskell}.
95+
96+\section{Message Reporting}
97+
98+Displaying errors to the user is not as simple as it might initially seem. For the type checker to be as helpful as possible, error messages should display the encountered issues in the language contexts in which they had occurred. Ideally, the errors should point to the exact terms that are most likely problematic.
99+
100+Even if all of the information necessary for detailed error messages is collected during type checking, displaying errors to the user is a problem that deserves its own research\footnote{This also relates to how types are laid out when displaying to the user even when no errors have occurred.}. The users might have different screen sizes. The error message should reflow all of the displayed text, code, and type annotations to accommodate the available space.
101+
102+Hughes introduced a general-purpose algebraic pretty-printer~\cite{hughes1995design}, which was later improved upon~\cite{wadler2003prettier}, to solve precisely this problem. Using one of the pretty-printers based on that research is the industry standard and will be used by our type checker.
103+
104+\section{Language Server Architecture}
105+
106+A Language Server is a server providing language-specific code analysis. It communicates with various code editors using the Language Server Protocol\footnote{\url{https://microsoft.github.io/language-server-protocol/}}.
107+
108+Language Servers have received wide adoption across a large variety of programming languages. Integrating the developed type checker into a Language Server with ``go-to-definition'' and ``show types on hover'' support would significantly improve the experience of developing in the Nix Expression Language.
109+
110+One of the actively developed language servers is the Haskell Language Server\footnote{\url{https://github.com/haskell/haskell-language-server}}. To manage the complexities of tracking changes in files and dependencies between them, the Haskell Language Server employs the Shake library~\cite{mitchell2012shake}. It is described as an alternative to Make\footnote{\url{https://www.gnu.org/software/make/}} embedded as a DSL into Haskell with the ability to dynamically update the dependency tree, among other improvements.
111+
112+As it is already tested as the basis for a Language Server implementation, building our Language Server on top of the Shake library seems like the correct architectural decision.
113+
114+\section{Conclusion}
115+
116+Nix is a rapidly growing ecosystem. At the time of writing, nixpkgs, the Nix package registry, contains over 60000 packages\footnote{\url{https://github.com/NixOS/nixpkgs}} that can be either installed or used as dependencies in other projects. There is much interest in the approach used by Nix, and making the ever-growing codebase of configurations easier to manage and extend would be a welcome development.
117+
118+Even though the developed type checker will need to check code for an existing dynamic language, and no type checker can cover all of the valid cases, producing false negatives, covering most of the cases encountered in practice would be useful enough to be worth using. Furthermore, plenty of research has already been conducted on which the Nix Expression Language type checker can be based.
119+
120+Integrating the type checker into a Language Server would provide additional utility and afford the ability to implement additional features, such as ``go-to-definition'' in a practical way.
121+
122+
123+\bibliographystyle{IEEEtran}
124+\bibliography{bibl}
125+
126+\begin{flushright}
127+ \vspace{1cm}
128+ \fbox{\textsc{\textsf{\textbf{\large word count: 1593}}}}
129+\end{flushright}
130+
131+\end{document}
docs/tech_spec.texnew file+288
@@ -0,0 +1,288 @@
1+\documentclass[12pt]{article}
2+
3+\usepackage{xcolor}
4+\usepackage[hidelinks]{hyperref}
5+
6+\newcommand{\todo}{\addcontentsline{toc}{subsection}{{\color{red}\textbf{TODO}}}{\LARGE\color{red}\textbf{TODO}}}
7+
8+\newcounter{req}
9+
10+\newcommand{\req}[1][]{\refstepcounter{req}\label{req:#1}\paragraph{\fbox{\textsf{\textsc{REQ}-\thereq}}}}
11+\newcommand{\refreq}[1]{\hyperref[req:#1]{\fbox{\textsf{REQ-\ref*{req:#1}}}}}
12+
13+\title{Technical Specification for the Language Server for the Nix Expression Language}
14+\author{Kostyuchenko Ilya}
15+\date{}
16+
17+\begin{document}
18+
19+\maketitle
20+
21+\newpage
22+
23+\tableofcontents
24+
25+\newpage
26+
27+\section{Purpose}
28+
29+The purpose of Tix is to simplify development in the Nix expression language.
30+
31+\section{Scope}
32+
33+The project consists of developing the following components:
34+
35+\paragraph{The Tix type checker} is a program which is designed to statically analyze the given Nix expression language source code and deduce the types of subexpressions used within while detecting some errors made by the programmer (type mismatch errors, which usually arise due to programming mistakes).
36+
37+\paragraph{The Tix language server} is a program which implements the Language Server Protocol and is used to integrate the Tix type checker with existing code editors to aid with development.
38+
39+\section{Product perspective}
40+
41+\subsection{System interfaces}
42+
43+The application runs on the latest versions of macOS and Linux.
44+
45+\subsection{User interfaces}
46+
47+The application does not provide a user interface.
48+
49+\subsection{Hardware interfaces}
50+
51+The application does not provide a hardware interface.
52+
53+\subsection{Software interfaces}
54+
55+The application allows interactions through the Language Server Protocol.
56+
57+\subsection{Communications interfaces}
58+
59+The application communicates with the code editor process through the Language Server Protocol using JSON-RPC requests. These requests can be over the network or local to the machine โ€“ however, the user decides to set it up.
60+
61+\subsection{Memory}
62+
63+The memory required to run the system depends on the size of the project being processed. Typical projects should are processed within a 2 GB memory limit.
64+
65+\subsection{Operations}
66+
67+The application supports the following operations initiated by the code editor:
68+
69+\begin{enumerate}
70+ \item Typecheck the current file and report errors
71+ \item Go to the definition of a variable
72+ \item Identify the type of a selected expression expression
73+\end{enumerate}
74+
75+\subsection{Site adaptation requirements}
76+
77+No site adaptations are required.
78+
79+\subsection{Interfaces with services}
80+
81+No interaction with services in performed.
82+
83+\section{Product functions}
84+
85+The application provides the following functionality to the user:
86+
87+\begin{enumerate}
88+ \item While the user is editing a Nix expression language file the application will indicate potentially incorrect subexpressions based on type mismatches
89+ \item While the user is exploring a Nix expression language project the application will provide:
90+ \begin{enumerate}
91+ \item type information for subexpressions the user is inspecting
92+ \item definitions of variables a user is inspecting
93+ \end{enumerate}
94+\end{enumerate}
95+
96+\section{User characteristics}
97+
98+The user of the application will need intermediate technical skills to set up the application to work with their text editor of choice. More precisely, the user will need to have the following (approximate and incomplete) list of skills:
99+
100+\begin{enumerate}
101+ \item Understand on a high level what a language server is and its role in code editing
102+ \item Be familiar with the repositories of packages for their text editor of choice
103+ \item Be able to perform intermediate configuration of their text editor of choice and installed packages
104+ \item Have basic server administration skills if they are planning to run the server remotely
105+\end{enumerate}
106+
107+\section{Limitations}
108+
109+\subsection{Interface to other applications}
110+
111+The integration with the text editor of choice should be compatible with version 3.15 of the Language Server Protocol.
112+
113+\subsection{Criticality of the application}
114+
115+The software should not be used for critical applications as it is not capable of eliminating all runtime errors, or even eliminating all runtime type errors due to the dynamic nature of the underlying Nix expression language\footnote{Type systems inherently restrict some valid programs, and some expressions might not be well-typed, but execute without errors.}.
116+
117+\section{Assumptions and dependencies}
118+
119+The contents of this document assume the following:
120+
121+\begin{enumerate}
122+ \item The application will be used on a UNIX-like system that is supported by the Glasgow Haskell Compiler.
123+ \item All dependencies of the files being processed should be locally downloaded by Nix.
124+\end{enumerate}
125+
126+\section{Apportioning of requirements}
127+
128+The application is a self-contained executable file that, when executed, functions as a standalone language server. The only requirement that the application externally imposes is the requirement to set up the language sever to function with the desired text editor. There already exist numerous implementation for language server support for many text editors.
129+
130+\section{Specified requirements}
131+
132+\req[restrictons] The system should perform all static program analysis (instances of such analysis link to this requirement) under the following conditions:
133+\begin{enumerate}
134+ \item it is possible to perform analysis without (partially) evaluating expressions
135+ \item all input data linked to from the expressions being analyzed is locally downloaded by Nix
136+\end{enumerate}
137+
138+\req[typechecking] The system should perform type checking for expression where under conditions from \refreq{restrictons}.
139+
140+\req The system should analyze conditional statements where the condition consists only of type checks and boolean operators built into the Nix expression language.
141+
142+\req The system should analyze the types and presence of attributes in attribute sets under conditions from \refreq{restrictons}.
143+
144+\req The system should report encountered typechecking errors through means defined by the Language Server Protocol.
145+
146+\req The system should provide the location of definitions for all locally used terms under conditions from \refreq{restrictons}.
147+
148+\req The system should report the use of undefined terms through means defined by the Language Server Protocol under conditions from \refreq{restrictons}.
149+
150+\req The system should report the types of requested expressions through means defined by the Language Server Protocol if the type of the requested expression is unambiguously inferable during typechecking (\refreq{typechecking}).
151+
152+\req The system should provide code completions suggestions from the variables currently in scope and expressions built into the language under conditions from \refreq{restrictons}.
153+
154+\req The system should provide a way for the programmer to explicitly annotate types of expressions which will influence type checking.
155+
156+\section{Usability requirements}
157+
158+\req The system should be able to process expressions using the nixpkgs repository.
159+
160+\req The system should never fail in unrecoverable ways in external imported expressions โ€“ if there are type errors in external code the system should resolve the errors automatically.
161+
162+\section{Performance requirements}
163+
164+\req The system should process incoming requests within 1 second (the system should formulate a response, not necessarily finish performing the requested action).
165+
166+\req The system should process incoming requests from a single client.
167+
168+\section{External interfaces}
169+
170+The only external interface of the system is the Language Server Protocol.
171+
172+\paragraph{The purpose} of this interface is to provide easy interoperability with a wide range of potential code editors a user might want to use\footnote{\url{https://microsoft.github.io/language-server-protocol/implementors/tools/}}.
173+
174+\paragraph{The source of input} is the code editor the user uses sending requesting information about the semantics of the file currently being edited in response to the actions the user is taking while browsing or editing source code in the Nix expression language.
175+
176+\paragraph{The destination of the input} is the code editor the user is using which has requested information about the source code.
177+
178+\paragraph{Data and command formats} are defined by the Language Server Protocol\footnote{\url{https://microsoft.github.io/language-server-protocol/specifications/specification-current/}}.
179+
180+\section{Functions}
181+
182+The fundamental functions of the system are queries: get the type of an expression, get the definition of a variable, get code completion. All of the responses to the queries can be generated from an \emph{analysis context} which is generated from the current file the user is viewing and any other files it imports.
183+
184+If the context \emph{analysis context} is already generated then the responses are formulated as follows. If the \emph{analysis context} is not present, then it is generated prior to processing the request.
185+
186+\subsection{Generating the type of an expression}
187+
188+\begin{enumerate}
189+ \item the system queries the expression at the requested position in the source code from the \emph{analysis context}
190+ \item the system queries the type of the expression from the \emph{analysis context}
191+ \item the system returns the type
192+\end{enumerate}
193+
194+\subsection{Generating the definition of a variable}
195+
196+\begin{enumerate}
197+ \item the system queries the expression at the requested position in the source code from the \emph{analysis context}
198+ \item the system asserts that the expression is a variable reference
199+ \item the system queries the definition of the given variable reference from the \emph{analysis context}
200+ \item the system returns the definition
201+\end{enumerate}
202+
203+\subsection{Generating completions}
204+
205+\begin{enumerate}
206+ \item the system queries the variables in scope at the requested position in the source code from the \emph{analysis context}
207+ \item the system formulates a list of possible completions
208+ \item the system filters the list of possible completions based on the prefix already typed by the user
209+ \item the system returns the list of filtered possible completions
210+\end{enumerate}
211+
212+\subsection{Generating the analysis context}
213+
214+\begin{enumerate}
215+ \item the current file is parsed
216+ \item dependencies are gathered from the current file and the analysis context is recursively generated for all dependencies
217+ \item the current file is typechecked
218+ \begin{enumerate}
219+ \item type constraints are recursively generated for all subexpressions
220+ \item encountered variable definitions are gathered
221+ \item encountered variable references are gathered
222+ \item undefined variable definitions are gathered
223+ \item type constraints are generated for the given top-level expression
224+ \item type constraints are sequentially solved. If a typing error is encountered, the error is gathered with other errors and the problematic type is replaced with a polymorphic type to allow further typechecking
225+ \end{enumerate}
226+ \item all errors gathered during typechecking are reported to the user through means defined by the Language Server Protocol
227+ \item all analysis contexts are merged into a single analysis context
228+ \item the resulting analysis context is the returned
229+\end{enumerate}
230+
231+\subsection{Error handling}
232+
233+If the system encounters a typing error in the user's code, then the error is returned to the user through means defined in the Language Serer Protocol.
234+
235+If the system encounters an internal (as opposed to a user error) the error is written to the standard error output.
236+
237+\section{Design constraints}
238+
239+The main design constraint is the fact that the Nix expression language is a dynamic language without an underlying static type system. This implies that there will be correct programs that will be ill-typed. The system should be designed in such a way as to gracefully handle such situations.
240+
241+\section{Software system attributes}
242+
243+\subsection{Reliability}
244+
245+\begin{enumerate}
246+ \item The system should automatically recover from any user error after the user resolves the error in code.
247+ \item The system should not enter unrecoverable states.
248+\end{enumerate}
249+
250+\subsection{Maintainability}
251+
252+The system should utilize free monad algebraic effects for managing side-effects as they improve maintainability by decoupling implementation from abstraction.
253+
254+\subsection{Portability}
255+
256+\begin{enumerate}
257+ \item The system should not contain host-dependant code
258+ \item The system should be written in the Haskell programming language which is not host-dependent
259+ \item The system should be compiled with the Glasgow Haskell Compiler as it supports a wide range of platforms
260+\end{enumerate}
261+
262+\section{Verification}
263+
264+The following approaches and methods are planned to be employed to qualify the software:
265+
266+\begin{enumerate}
267+ \item Automated hand-written unit-tests
268+ \item Automated randomly generated property tests
269+ \item Manual testing
270+\end{enumerate}
271+
272+\section{Supporting information}
273+
274+\subsection{Nix}
275+
276+Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible.\footnote{Taken from \url{https://nixos.org}}.
277+
278+\subsection{Nix expression language}
279+
280+The Nix expression language is a purely functional dynamic strictly typed programming language used for configuration in the Nix package manager. It does not support defining custom types โ€“ all types are defined within the interpreter. The main purpose of the language is to produce \emph{derivation} โ€“ a description of how to build an artifact\footnote{\url{https://nixos.org/manual/nix/stable/\#ssec-derivation}}.
281+
282+\subsection{The problem to be solved}
283+
284+When working with the Nix expression language it is often the case that imported expressions (nixpkgs) are quite large, and it is not obvious what needs to be called with what arguments. It is often necessary to inspect the source code of imported files to grok how it should be used and if the current use is correct.
285+
286+This project aims to lighten the burden of development in the Nix expression language by providing some level of machine-generated introspection into the imported expressions and provide some level of verification of the correctness of the implementation.
287+
288+\end{document}
tix.code-workspacenew file+12
@@ -0,0 +1,12 @@
1+{
2+ "folders": [
3+ {
4+ "name": "Tix",
5+ "path": "."
6+ },
7+ {
8+ "name": "Tix Docs",
9+ "path": "docs"
10+ }
11+ ]
12+}