├── .gitattributes
├── gc.dhall
├── mac.dhall
├── no-gc.dhall
├── SATS
├── nproc.sats
├── utils.sats
├── error.sats
├── print.sats
└── filetype.sats
├── screenshot.png
├── .gitignore
├── perl
└── simple-linecount
├── .atsfmt.toml
├── compleat
└── poly.usage
├── bash
├── next
├── update
├── release
├── buildall
└── install.sh
├── CATS
└── nproc.cats
├── include
└── pthread_mac.h
├── .yamllint
├── DATS
├── error.dats
├── version.dats
├── utils.dats
├── count-loop.dats
├── cli.dats
├── html.dats
└── shared.dats
├── test
├── test.dats
├── bench.dats
└── data
│ ├── cli.dats
│ ├── Coq.v
│ ├── verilog.v
│ └── Python.y
├── .ctags
├── LICENSE
├── man
└── poly.md
├── CONTRIBUTING.md
├── src
├── compat.dats
└── polyglot.dats
├── .travis.yml
├── CHANGELOG.md
├── atspkg.dhall
├── TODO.md
├── README.md
└── LANGUAGES.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | test/data/* linguist-vendored
2 |
--------------------------------------------------------------------------------
/gc.dhall:
--------------------------------------------------------------------------------
1 | { gc = True, cross = True, parallel = True, static = True }
2 |
--------------------------------------------------------------------------------
/mac.dhall:
--------------------------------------------------------------------------------
1 | { gc = True, cross = True, parallel = True, static = False }
2 |
--------------------------------------------------------------------------------
/no-gc.dhall:
--------------------------------------------------------------------------------
1 | { gc = False, cross = True, parallel = True, static = True }
2 |
--------------------------------------------------------------------------------
/SATS/nproc.sats:
--------------------------------------------------------------------------------
1 | fn get_nprocs { m : nat | m > 0 }() : int(m) =
2 | "ext#"
3 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmchale/polyglot/HEAD/screenshot.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ignore
2 | postiats_funlablst_*
3 | tags
4 | .pijul
5 | .atspkg
6 | *.c
7 | target
8 | poly.1
9 | *.gz
10 |
--------------------------------------------------------------------------------
/perl/simple-linecount:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | perl -0777 -i -pe 's/```\n----.*```/```\n'"$(poly -c -e data)"'\n```/igs' README.md
3 |
--------------------------------------------------------------------------------
/.atsfmt.toml:
--------------------------------------------------------------------------------
1 | ribbon = 1.0 # maximum ribbon fraction
2 | width = 120 # maximum width
3 | clang-format = true # call clang-format on inline code
4 |
--------------------------------------------------------------------------------
/compleat/poly.usage:
--------------------------------------------------------------------------------
1 | poly (
| (-h | --help) | (-V | --version) | (-v | --verbose) | (-p | --no-parallel) | (-c | --no-color) | (-t | --no-table) | --html (--no-style)) | ((-e | --excludes) )) ... ;
2 |
--------------------------------------------------------------------------------
/SATS/utils.sats:
--------------------------------------------------------------------------------
1 | staload "SATS/filetype.sats"
2 |
3 | fn eq_pl_type(x : !pl_type, y : !pl_type) : bool
4 |
5 | overload = with eq_pl_type
6 |
7 | fn free_pl(pl_type) : void
8 |
9 | overload free with free_pl
10 |
11 | // monoidal addition for 'file' type
12 | fn add_results(file, file) : file
13 |
14 | overload + with add_results
15 |
--------------------------------------------------------------------------------
/SATS/error.sats:
--------------------------------------------------------------------------------
1 | // This file contains various error functions.
2 | fn redundant_cli_flag() : void
3 |
4 | fn bad_file(string) : void
5 |
6 | fn bad_directory(string) : void
7 |
8 | fn bad_flag(string) : void
9 |
10 | fn error_flag(string) : void
11 |
12 | fn internal_error() : void
13 |
14 | fn bad_exclude(string) : void
15 |
16 | fn maybe_err(string) : void
17 |
--------------------------------------------------------------------------------
/SATS/print.sats:
--------------------------------------------------------------------------------
1 | // This file contains various functions for printing generated output
2 | staload "SATS/filetype.sats"
3 | staload "libats/ML/SATS/string.sats"
4 |
5 | fun print_file(pt : !pl_type, string) : string
6 |
7 | // function to print tabular output at the end
8 | fn make_table(source_contents, bool) : string
9 |
10 | // Function to print output sorted by type of language.
11 | fn make_output(source_contents, bool) : string
12 |
--------------------------------------------------------------------------------
/bash/next:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e pipefail
4 |
5 | VERSION="$(grep -P -o '\d+\.\d+\.\d+' DATS/cli.dats | tail -n1)"
6 | VERSION_COMMA="$(echo "$VERSION" | sed 's/\./,/g')"
7 | NEW_VERSION_SP="$(echo "$VERSION" | awk -F. '{$NF+=1; print $0}')"
8 | NEW_VERSION="$(echo "$NEW_VERSION_SP" | sed 's/ /\./g')"
9 | NEW_VERSION_COMMA="$(echo "$NEW_VERSION_SP" | sed 's/ /,/g')"
10 |
11 | echo "$NEW_VERSION"
12 |
13 | sed -i "s/$VERSION/$NEW_VERSION/" DATS/cli.dats
14 | sed -i "s/$VERSION_COMMA/$NEW_VERSION_COMMA/" atspkg.dhall
15 |
16 | git commit -am "version bump"
17 |
--------------------------------------------------------------------------------
/CATS/nproc.cats:
--------------------------------------------------------------------------------
1 | // from here: https://stackoverflow.com/a/22330309
2 | #ifdef __APPLE__
3 | int get_nprocs() {
4 | int count;
5 | size_t count_len = sizeof(count);
6 | sysctlbyname("hw.logicalcpu", &count, &count_len, NULL, 0);
7 | return count;
8 | }
9 | #elif defined(__x86_64__) && !defined(__linux__)
10 | extern int get_nprocs() {
11 | int t;
12 |
13 | asm volatile (
14 | "cpuid\n"
15 | "mov %0, %%eax\n"
16 | "shr $0x10, %0\n"
17 | "and $0xf, %0\n"
18 | "dec %0"
19 | : "=r" (t)
20 | );
21 |
22 | return t;
23 | }
24 | #endif
25 |
--------------------------------------------------------------------------------
/bash/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -ex pipefail
3 | latest="$(curl -s https://github.com/AlDanial/cloc/releases/latest/ | cut -d'"' -f2 | rev | cut -d'/' -f1 | rev)"
4 | wget "https://github.com/AlDanial/cloc/releases/download/$latest/cloc-$latest.pl" -O "$HOME/.local/bin/cloc"
5 | chmod +x "$HOME/.local/bin/cloc"
6 | go get -u github.com/boyter/scc/
7 | go get -u gopkg.in/src-d/enry.v1/...
8 | # go get -u github.com/hhatto/gocloc/cmd/gocloc
9 | # sudo gem install github-linguist
10 | # TODO: figure out update process for github-linguist
11 | rustup update
12 | cargo install loc --force
13 | cargo install tokei --force
14 |
--------------------------------------------------------------------------------
/include/pthread_mac.h:
--------------------------------------------------------------------------------
1 | // taken from: https://github.com/majek/dump/blob/master/msqueue/pthread_spin_lock_shim.h
2 | #include
3 |
4 | #ifdef __APPLE__
5 |
6 | typedef int pthread_spinlock_t;
7 |
8 | static inline int pthread_spin_init(pthread_spinlock_t *lock, int pshared) {
9 | __asm__ __volatile__ ("" ::: "memory");
10 | *lock = 0;
11 | return 0;
12 | }
13 |
14 | static inline int pthread_spin_destroy(pthread_spinlock_t *lock) {
15 | return 0;
16 | }
17 |
18 | static inline int pthread_spin_lock(pthread_spinlock_t *lock) {
19 | while (1) {
20 | int i;
21 | for (i=0; i < 10000; i++) {
22 | if (__sync_bool_compare_and_swap(lock, 0, 1)) {
23 | return 0;
24 | }
25 | }
26 | sched_yield();
27 | }
28 | }
29 |
30 | static inline int pthread_spin_trylock(pthread_spinlock_t *lock) {
31 | if (__sync_bool_compare_and_swap(lock, 0, 1)) {
32 | return 0;
33 | }
34 | return EBUSY;
35 | }
36 |
37 | static inline int pthread_spin_unlock(pthread_spinlock_t *lock) {
38 | __asm__ __volatile__ ("" ::: "memory");
39 | *lock = 0;
40 | return 0;
41 | }
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/.yamllint:
--------------------------------------------------------------------------------
1 | ---
2 | rules:
3 | braces:
4 | min-spaces-inside: 0
5 | max-spaces-inside: 0
6 | min-spaces-inside-empty: -1
7 | max-spaces-inside-empty: -1
8 | brackets:
9 | min-spaces-inside: 0
10 | max-spaces-inside: 0
11 | min-spaces-inside-empty: -1
12 | max-spaces-inside-empty: -1
13 | colons:
14 | max-spaces-before: 0
15 | max-spaces-after: 1
16 | commas:
17 | max-spaces-before: 0
18 | min-spaces-after: 1
19 | max-spaces-after: 1
20 | comments:
21 | level: warning
22 | require-starting-space: true
23 | min-spaces-from-content: 2
24 | comments-indentation:
25 | level: warning
26 | document-end: disable
27 | document-start:
28 | level: warning
29 | present: true
30 | empty-lines:
31 | max: 2
32 | max-start: 0
33 | max-end: 0
34 | hyphens:
35 | max-spaces-after: 1
36 | indentation:
37 | spaces: consistent
38 | indent-sequences: true
39 | check-multi-line-strings: false
40 | key-duplicates: enable
41 | line-length: disable
42 | new-line-at-end-of-file: enable
43 | new-lines:
44 | type: unix
45 | trailing-spaces: enable
46 | truthy: disable
47 |
--------------------------------------------------------------------------------
/DATS/error.dats:
--------------------------------------------------------------------------------
1 | staload "libats/ML/SATS/string.sats"
2 | staload "SATS/error.sats"
3 |
4 | implement redundant_cli_flag () =
5 | prerr!("\33[33mWarning:\33[0m Flag -s/--no-style has no effect when --html is not present\n")
6 |
7 | implement bad_file (s) =
8 | if s != "" then
9 | prerr!("\33[33mWarning:\33[0m could not open file at " + s + "\n")
10 | else
11 | ()
12 |
13 | implement bad_directory (s) =
14 | (prerr!("\33[31mError:\33[0m flag " + s + " found where a directory name was expected\n") ; exit(1))
15 |
16 | implement bad_flag (s) =
17 | (prerr!("\33[31mError:\33[0m flag " + s + " must appear occur at most once\n") ; exit(1))
18 |
19 | implement error_flag (s) =
20 | (prerr!("\33[31mError:\33[0m flag '" + s + "' not recognized. Try 'poly --help'\n") ; exit(1))
21 |
22 | implement internal_error () =
23 | (prerr!("\33[31mError:\33[0m internal error\n") ; exit(1))
24 |
25 | implement bad_exclude (s) =
26 | (prerr!("\33[31mError:\33[0m flag "
27 | + s
28 | + " must be followed by an argument and must occur alone\n") ; exit(1))
29 |
30 | implement maybe_err (next) =
31 | (prerr("\33[31mError:\33[0m directory '" + next + "' does not exist\n") ; exit(1))
32 |
--------------------------------------------------------------------------------
/test/test.dats:
--------------------------------------------------------------------------------
1 | #include "share/atspre_staload.hats"
2 | #include "share/HATS/atslib_staload_libats_libc.hats"
3 | #include "DATS/shared.dats"
4 | #include "$PATSHOMELOCS/specats-0.2.3/mylibies.hats"
5 | #include "DATS/utils.dats"
6 | #include "DATS/error.dats"
7 |
8 | fn test_file(s : string, expected : pl_type) : bool =
9 | let
10 | var t0_actual = prune_extension("test/data/" + s, s)
11 | val b = expected = t0_actual
12 | val _ = free(expected)
13 | val _ = free(t0_actual)
14 | in
15 | b
16 | end
17 |
18 | implement main0 () =
19 | {
20 | var e = empty_file
21 | var t0_expected = happy(e)
22 | var b0 = test_file("Python.y", t0_expected)
23 | var n0 = @{ fst = "happy", snd = b0 }
24 | var t1_expected = yacc(e)
25 | var b1 = test_file("rust.y", t1_expected)
26 | var n1 = @{ fst = "yacc", snd = b1 }
27 | var t2_expected = coq(e)
28 | var b2 = test_file("Coq.v", t2_expected)
29 | var n2 = @{ fst = "coq", snd = b2 }
30 | var t3_expected = verilog(e)
31 | var b3 = test_file("verilog.v", t3_expected)
32 | var n3 = @{ fst = "verilog", snd = b3 }
33 | var xs = n0 :: n1 :: n2 :: n3 :: nil
34 | var total = list_vt_length(xs)
35 | val g = @{ group = "Overlaps", leaves = xs } : test_tree
36 | val _ = iterate_list(g, 0, total)
37 | }
38 |
--------------------------------------------------------------------------------
/.ctags:
--------------------------------------------------------------------------------
1 | --langdef=ATS
2 | --langmap=ATS:.dats
3 | --langmap=ATS:+.sats
4 | --langdef=DHALL
5 | --langmap=DHALL:.dhall
6 | --regex-ATS=/^fun *([[:lower:]][[:alnum:]_]+)[[:blank:]]*[\(\[\{)]/\1/f,function/
7 | --regex-ATS=/^fn *([[:lower:]][[:alnum:]_]+)[[:blank:]]*[\(\[\{)]/\1/f,function/
8 | --regex-ATS=/^prfun *([[:lower:]][[:alnum:]_]+)[[:blank:]]*[\(\[\{)]/\1/f,function/
9 | --regex-ATS=/^fnx *([[:lower:]][[:alnum:]_]+)[[:blank:]]*[\(\[\{)]/\1/f,function/
10 | --regex-ATS=/^praxi *([[:lower:]][[:alnum:]_]+)[[:blank:]]*[\(\[\{)]/\1/p,proof/
11 | --regex-ATS=/^typedef *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
12 | --regex-ATS=/^datatype *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
13 | --regex-ATS=/^sortdef *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
14 | --regex-ATS=/^viewtypedef *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
15 | --regex-ATS=/^vtypedef *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
16 | --regex-ATS=/^dataviewtype *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
17 | --regex-ATS=/^datavtype *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,type/
18 | --regex-ATS=/^dataprop *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,proof/
19 | --regex-ATS=/^dataviewprop *([[:lower:]][[:alnum:]_]+)[[:blank:]]*=/\1/t,proof/
20 | --regex-DHALL=/let *([[:lower:]][[:alnum:]_]+)/\1/f,function/
21 | --regex-DHALL=/let *([[:upper:]][[:alnum:]_]+)/\1/t,type/
22 |
--------------------------------------------------------------------------------
/test/bench.dats:
--------------------------------------------------------------------------------
1 | #include "share/atspre_staload.hats"
2 | #include "share/HATS/atslib_staload_libats_libc.hats"
3 | #include "DATS/shared.dats"
4 | #include "$PATSHOMELOCS/ats-bench-0.3.3/bench.dats"
5 | #include "DATS/utils.dats"
6 | #include "DATS/error.dats"
7 |
8 | fun linecount_bench() : void =
9 | { val _ = line_count("DATS/cli.dats", Some_vt("//")) }
10 |
11 | fun flow_stream_bench() : void =
12 | {
13 | var x = empty_contents()
14 | val _ = step_stream(x, ".", ".", list_nil, false)
15 | }
16 |
17 | fun shebang_bench() : void =
18 | {
19 | val pl = check_shebang("bash/install.sh")
20 | val () = free(pl)
21 | }
22 |
23 | fun keyword_bench() : void =
24 | {
25 | var empty_file = @{ lines = 0, blanks = 0, comments = 0, files = 0 } : file
26 | val pl_t = check_keywords("test/data/Coq.v", empty_file, "v")
27 | val () = free(pl_t)
28 | }
29 |
30 | val linecount_delay = lam () => linecount_bench()
31 | val keyword_delay = lam () => keyword_bench()
32 | val stream_delay = lam () => flow_stream_bench()
33 | val shebang_delay = lam () => shebang_bench()
34 |
35 | implement main0 () =
36 | {
37 | val _ = print_slope("linecount (DATS/cli.dats)", 12, linecount_delay)
38 | val _ = print_slope("keyword check (test/data/Coq.v)", 9, keyword_delay)
39 | val _ = print_slope("step_stream", 6, stream_delay)
40 | val _ = print_slope("shebang check", 12, shebang_delay)
41 | }
42 |
--------------------------------------------------------------------------------
/bash/release:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -ex pipefail
4 |
5 | VERSION="$(grep -P -o '\d+\.\d+\.\d+' DATS/cli.dats | tail -n1)"
6 | TOKEN="$(cat "$HOME"/.git-token)"
7 |
8 | git tag "$VERSION"
9 | git push origin --tags
10 | git tag -d "$VERSION"
11 | git push origin master
12 |
13 | github-release release -s "$TOKEN" -u vmchale -r polyglot -t "$VERSION"
14 |
15 | for PLATFORM in s390x-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu powerpc-linux-gnu powerpc64-linux-gnu powerpc64le-linux-gnu alpha-linux-gnu mips-linux-gnu mipsel-linux-gnu mips64-linux-gnuabi64 mips64el-linux-gnuabi64 i686-linux-gnu sh4-linux-gnu riscv64-linux-gnu hppa-linux-gnu arm-linux-gnueabi # powerpc-linux-gnuspe # mipsisa32r6el-linux-gnu mipsisa32r6-linux-gnu mipsisa64r6el-linux-gnuabi64 mipsisa64r6-linux-gnuabi64
16 | do
17 | github-release upload -s "$TOKEN" -u vmchale -r polyglot -n poly-"$PLATFORM" -f target/poly-"$PLATFORM" -t "$VERSION" --replace
18 | done
19 |
20 | github-release upload -s "$TOKEN" -u vmchale -r polyglot -n poly.1 -f man/poly.1 -t "$VERSION" --replace
21 | github-release upload -s "$TOKEN" -u vmchale -r polyglot -n poly.usage -f compleat/poly.usage -t "$VERSION" --replace
22 | github-release upload -s "$TOKEN" -u vmchale -r polyglot -n polyglot.deb -f target/polyglot.deb -t "$VERSION" --replace
23 | github-release upload -s "$TOKEN" -u vmchale -r polyglot -n poly-x86_64-unknown-linux-gcc-9 -f target/poly -t "$VERSION" --replace
24 |
--------------------------------------------------------------------------------
/DATS/version.dats:
--------------------------------------------------------------------------------
1 | %{
2 |
3 | // see:
4 | // http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros#Howtodetectthecompilerversion
5 |
6 | #if defined(__clang__)
7 | void compiler_version(void) {
8 | printf("compiled with clang version: %d.%d.%d\n", __clang_major__,
9 | __clang_minor__, __clang_patchlevel__);
10 | }
11 | #elif defined(__GNUC__)
12 | void compiler_version(void) {
13 | printf("compiled with gcc version: %d.%d.%d\n", __GNUC__, __GNUC_MINOR__,
14 | __GNUC_PATCHLEVEL__);
15 | }
16 | #elif defined(__INTEL_COMPILER)
17 | void compiler_version(void) {
18 | int icc_major;
19 | int icc_minor;
20 | icc_major = __INTEL_COMPILER / 100;
21 | icc_minor = __INTEL_COMPILER % 100;
22 |
23 | printf("compiled with icc version: %d.%d\n", icc_major, icc_minor);
24 | }
25 | #elif defined(__PGIC__)
26 | void compiler_version(void) {
27 | prinf("compiled with pgcc version: %d.%d\n", __PGIC__,
28 | __PGIC_PATCHLEVEL__);
29 | }
30 | #else
31 | void compiler_version(void) {}
32 | #endif
33 |
34 | #if defined(__GLIBC__)
35 | #include
36 |
37 | void libc_version(void) {
38 | printf("glibc version: %d.%d\n", __GLIBC__, __GLIBC_MINOR__);
39 | }
40 | #else
41 | void libc_version(void) {}
42 | #endif
43 | %}
44 |
45 | extern
46 | fn compiler_version() : void =
47 | "ext#"
48 |
49 | extern
50 | fn libc_version() : void =
51 | "ext#"
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Vanessa McHale (c) 2017-2020
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 |
7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 |
9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 |
--------------------------------------------------------------------------------
/man/poly.md:
--------------------------------------------------------------------------------
1 | % poly (1)
2 | % Vanessa McHale
3 |
4 | # NAME
5 |
6 | poly - a command-line tool for counting source code
7 |
8 | # SYNOPSIS
9 |
10 | poly [DIRECTORY]... [OPTION]...
11 |
12 | # DESCRIPTION
13 |
14 | **poly** determines the contents of projects, giving a breakdown of all
15 | languages present.
16 |
17 | When no directory is given, polyglot will execute in the current directory.
18 |
19 | # OPTIONS
20 |
21 | **-h**, **-\-help** Display help and exit
22 |
23 | **-v**, **-\-version** Display version and exit
24 |
25 | **-e**, **-\-exclude** Exclude a directory
26 |
27 | **-p**, **-\-no-parallel** Do not execute in parallel. Concurrency is already
28 | disabled on some platforms.
29 |
30 | **-t**, **-\-no-table** Show results in an alternate format.
31 |
32 | **-p**, **-\-no-color** Don't colorize output
33 |
34 | **-v**, **-\-verbose** Enable per-file output
35 |
36 | **-\-html** Dump HTML output
37 |
38 | **-s**, **-\-no-style** Do not dump CSS styles with HTML output
39 |
40 | # EXAMPLES
41 |
42 | Show the contents of ~/programming
43 |
44 | ```
45 | poly ~/programming
46 | ```
47 |
48 | Count lines of source code in the current directory, skipping any directory called forks
49 |
50 | ```
51 | poly -e forks
52 | ```
53 |
54 | Show the contents of ./project/src, displaying an alternate output in the terminal
55 |
56 | ```
57 | poly ./project/src --no-table
58 | ```
59 |
60 | Write a file called report.html containing line count information from the
61 | current directory
62 |
63 | ```
64 | poly --html > report.html
65 | ```
66 |
67 | Append line count information in HTML to README.md
68 |
69 | ```
70 | poly --html --no-table >> README.md
71 | ```
72 |
73 | # BUG REPORTS
74 |
75 | For bug reports and updates, go to https://github.com/vmchale/polyglot/issues
76 |
--------------------------------------------------------------------------------
/bash/buildall:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | atspkg build --pkg-args './gc.dhall'
6 | # atspkg build --pkg-args "./gc.dhall" target/polyglot.deb
7 | atspkg build --pkg-args "./gc.dhall" --target=s390x-linux-gnu
8 | atspkg build --pkg-args "./gc.dhall" --target=arm-linux-gnueabihf
9 | atspkg build --pkg-args "./gc.dhall" --target=powerpc64-linux-gnu
10 | atspkg build --pkg-args "./gc.dhall" --target=powerpc64le-linux-gnu
11 | atspkg build --pkg-args "./gc.dhall" --target=powerpc-linux-gnu
12 | # atspkg build --pkg-args "./gc.dhall" --target=powerpc-linux-gnuspe
13 | atspkg build --pkg-args "./gc.dhall" --target=aarch64-linux-gnu
14 | atspkg build --pkg-args "./gc.dhall" --target=alpha-linux-gnu
15 | atspkg build --pkg-args "./gc.dhall" --target=m68k-linux-gnu
16 | atspkg build --pkg-args "./gc.dhall" --target=mips-linux-gnu
17 | atspkg build --pkg-args "./gc.dhall" --target=mipsel-linux-gnu
18 | atspkg build --pkg-args "./gc.dhall" --target=mips64-linux-gnuabi64
19 | atspkg build --pkg-args "./gc.dhall" --target=mips64el-linux-gnuabi64
20 | atspkg build --pkg-args "./gc.dhall" --target=i686-linux-gnu
21 | atspkg build --pkg-args "./gc.dhall" --target=mipsisa32r6el-linux-gnu
22 | atspkg build --pkg-args "./gc.dhall" --target=mipsisa32r6-linux-gnu
23 | atspkg build --pkg-args "./gc.dhall" --target=mipsisa64r6el-linux-gnuabi64
24 | atspkg build --pkg-args "./gc.dhall" --target=mipsisa64r6-linux-gnuabi64
25 | atspkg build --pkg-args "./no-gc.dhall" --target=riscv64-linux-gnu
26 | atspkg build --pkg-args "./no-gc.dhall" --target=sh4-linux-gnu
27 | atspkg build --pkg-args "./no-gc.dhall" --target=hppa-linux-gnu
28 | atspkg build --pkg-args "./no-gc.dhall" --target=hppa64-linux-gnu
29 | atspkg build --pkg-args "./no-gc.dhall" --target=sparc64-linux-gnu
30 | atspkg build --pkg-args "./no-gc.dhall" --target=arm-linux-gnueabi
31 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Polyglot
2 |
3 | I emphatically welcome bug reports, issues you may encounter, documentation, and
4 | pull requests. Feature requests will likely be implemented if and only they are
5 | relatively small; however, feel free to request support for a particular
6 | language, no matter how niche.
7 |
8 | ## Getting started
9 |
10 | If you'd like ideas for ways to contribute, check out `TODO.md`. Feel free to
11 | open a PR or an issue if you need guidance on how to implement something.
12 |
13 | ## Navigating the Code
14 |
15 | ATS can be quite daunting. The following are things that are relatively easy to
16 | implement:
17 |
18 | * Adding a new file type and its associated extension (note that the name of
19 | a file type must be less than 20 characters; otherwise there will be a type
20 | error!)
21 | * Adding a new directory to ignore (e.g. `.cabal-sandbox`)
22 | * Adding new shebang detection
23 | * Updating the `--help` or manpage.
24 | * Adding keywords to disambiguate extensions.
25 |
26 | If you have any trouble figuring this out, feel free to open an issue and I will
27 | give you guidance on where to look. I am occasionally in the `##ats` IRC
28 | channel, and you can ask me any questions about the code that you'd like.
29 |
30 | ## Rules etc.
31 | We follow the [rust standards of
32 | conduct](https://www.rust-lang.org/en-US/conduct.html), with the addendum that
33 | we are committed to providing a friendly, safe and welcoming environment
34 | regardless of sex worker status or previous sex worker status.
35 |
36 | In addition, please be aware that not everyone speaks English as a first
37 | language.
38 |
39 | ## Building
40 |
41 | In order to build, you will first need to install the tooling mentioned in the
42 | `README.md`. Make sure your code passes
43 |
44 | ```bash
45 | $ atspkg test
46 | ```
47 |
--------------------------------------------------------------------------------
/src/compat.dats:
--------------------------------------------------------------------------------
1 | #include "share/atspre_staload.hats"
2 | #include "share/HATS/atslib_staload_libats_libc.hats"
3 | #include "DATS/shared.dats"
4 | #include "$PATSHOMELOCS/edit-distance-0.5.0/DATS/edit-distance.dats"
5 | #include "DATS/utils.dats"
6 | #include "DATS/error.dats"
7 | #include "DATS/html.dats"
8 |
9 | implement main0 (argc, argv) =
10 | let
11 | val cli = @{ version = false
12 | , help = false
13 | , no_table = false
14 | , html = false
15 | , no_parallel = false
16 | , no_colorize = false
17 | , skip_links = false
18 | , verbose = false
19 | , excludes = list_nil()
20 | , includes = list_nil()
21 | } : command_line
22 | val parsed = get_cli(argc, argv, 0, false, cli)
23 | val () = check_cli(parsed)
24 | in
25 | if parsed.help then
26 | (help() ; exit(0))
27 | else
28 | if parsed.version then
29 | (version() ; exit(0))
30 | else
31 | let
32 | var result = if length(parsed.includes) > 0 then
33 | let
34 | var x = empty_contents()
35 | val () = map_stream(x, parsed.includes, parsed.excludes, parsed.verbose)
36 | in
37 | x
38 | end
39 | else
40 | let
41 | var x = empty_contents()
42 | val () = map_stream(x, list_cons(".", list_nil()), parsed.excludes, parsed.verbose)
43 | in
44 | x
45 | end
46 | in
47 | if parsed.no_table then
48 | print(make_output(result, not(cli.no_colorize)))
49 | else
50 | if parsed.html then
51 | print(make_html(result))
52 | else
53 | print(make_table(result, not(cli.no_colorize)))
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | matrix:
3 | include:
4 |
5 | - env: TARGET="x86_64-unknown-linux"
6 | os: linux
7 | language: python
8 |
9 | # OS X
10 | - env: TARGET="x86_64-apple-darwin"
11 | os: osx
12 | language: c
13 |
14 | cache:
15 | directories:
16 | - $HOME/.atspkg
17 | - $HOME/.local
18 |
19 | install:
20 | - export PATH=$HOME/.local/bin:$PATH
21 | - curl -sSl https://raw.githubusercontent.com/vmchale/atspkg/master/bash/install.sh | bash -s
22 | - |
23 | if [ $TARGET = "x86_64-unknown-linux" ]
24 | then
25 | pip install yamllint
26 | fi
27 | - atspkg -V
28 |
29 | script:
30 | - atspkg nuke
31 | - curl -sL https://raw.githubusercontent.com/vmchale/tomlcheck/master/sh/check | sh -s .atsfmt.toml
32 | - |
33 | if [ $TARGET = "x86_64-unknown-linux" ]
34 | then
35 | travis_wait 40 atspkg test --pkg-args "./gc.dhall"
36 | yamllint .travis.yml
37 | yamllint .yamllint
38 | atspkg build --pkg-args "./gc.dhall" -vvv
39 | else
40 | travis_wait 40 atspkg build --pkg-args "./mac.dhall" -vvv
41 | mv target/poly poly-$TARGET
42 | fi
43 |
44 | deploy:
45 | api_key:
46 | secure: "A7A2h7iYFO8z+wK3He9W2Y18G5leAlPhAtL2/HtJsAL/rIog+K5MB1rn7lcSWFgXMimMA+aWmr5PQHPLstVqt6IZNv3O/LV4We95Yr5HhHH+QP76zDChzRTM++9eRX/AIAJB4mZgyguZXXYdco6m/4Wj5DO/I2gyniP3sajqOsEhCnASskhcCoQhp9XGWSiRgowWxiKvjfLDAR6Bt/B9lLfg+gTR9VTQGrbAbSzwEWb7qlRp9P5WHNzWaof7C+6NM7XP+OMwENEJ/5KKNXiHEbht0GpU6Mmga7PpB8W2NzsKoFaG2nOmp+iyzp9sl+oC0pBycxX7n2+unDoW04kJPTLYNBW+xN/yj7c0Ioujnq4XXJWCckpwg4pK7/zj6FeQJULAHplCEZf5HxCBPZ1TnvsfpdqeYD1Vjf/B0DzVnvhrPDasG0Et1iFedBvc9YL7fkyypc45ySXbnRlupr5KknMGqIUrC0QiY0jP9+LGTfWu4IoN3ArUItcfs/D99w6PH82FU9Z+AkDEWHaVtPwXN9y43Pt1p7vuIszCYY3/So1TrFtmPwsYnjVIiKrhQIzx2N5tN9pyZiiQBY1QU5/k6kEXIdXXScGIJbT1qqcTqMduguguS6NDygiJ9nomFnUS0wPMpLKP5T31aAble6rWuHTlM0tyZ4l3qJbNSWPDUPw="
47 | file: poly-$TARGET
48 | on:
49 | tags: true
50 | provider: releases
51 | skip_cleanup: true
52 |
--------------------------------------------------------------------------------
/bash/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 | set pipefail
5 |
6 | getTarget() {
7 | if [ "$(uname)" = "Darwin" ]
8 | then
9 | echo "poly-$(uname -m)-apple-darwin"
10 | else
11 | case $(uname -m) in
12 | "armv7l") ARCH="arm";;
13 | *) ARCH="$(uname -m)";;
14 | esac
15 | case $ARCH in
16 | "x86_64") MACHINE="unknown-linux-gcc-9";;
17 | "arm") MACHINE="linux-gnueabihf";;
18 | "mips64"*) MACHINE="linux-gnuabi64";;
19 | *) MACHINE="linux-gnu";;
20 | esac
21 | echo "poly-$ARCH-$MACHINE"
22 | fi
23 | }
24 |
25 | addBin() {
26 |
27 | printf 'export PATH=$HOME/.local/bin:$PATH' >> "$HOME"/.bashrc
28 | export PATH=$HOME/.local/bin:$PATH
29 |
30 | }
31 |
32 | main() {
33 |
34 | latest="$(curl -s https://github.com/vmchale/polyglot/releases/latest/ | cut -d'"' -f2 | rev | cut -d'/' -f1 | rev)"
35 | binname=$(getTarget)
36 |
37 | mkdir -p "$HOME/.local/bin"
38 | mkdir -p "$HOME/.local/share/man/man1/"
39 | mkdir -p "$HOME/.compleat"
40 |
41 | dest=$HOME/.local/bin/poly
42 | man_dest=$HOME/.local/share/man/man1/poly.1
43 | compleat_dest=$HOME/.compleat/poly.usage
44 |
45 | if command -v wget > /dev/null ; then
46 | wget https://github.com/vmchale/polyglot/releases/download/"$latest"/"$binname" -O "$dest"
47 | wget https://github.com/vmchale/polyglot/releases/download/"$latest"/poly.1 -O "$man_dest"
48 | wget https://github.com/vmchale/polyglot/releases/download/"$latest"/poly.usage -O "$compleat_dest"
49 | else
50 | curl -L https://github.com/vmchale/polyglot/releases/download/"$latest"/"$binname" -o "$dest"
51 | curl -L https://github.com/vmchale/polyglot/releases/download/"$latest"/poly.1 -o "$man_dest"
52 | curl -L https://github.com/vmchale/polyglot/releases/download/"$latest"/poly.usage -o "$compleat_dest"
53 | fi
54 | chmod +x "$dest"
55 |
56 | case :$PATH: in
57 | *:$HOME/.local/bin:*) ;;
58 | *) addBin ;;
59 | esac
60 |
61 | }
62 |
63 | main
64 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # polyglot
2 |
3 | * Skip `.vagrant` directories
4 | * `Vagrantfile` detection
5 | * Support detection of GLSL shader/vertex fragments
6 | * Support detection of Mirth programs
7 |
8 | ## 0.5.27
9 |
10 | * Fancy command-line output
11 | * Add terraform + org-mode support
12 |
13 | ## 0.5.26
14 |
15 | * Add `.scss` detection
16 |
17 | ## 0.5.21
18 |
19 | * Skip `.pyre` directories
20 |
21 | ## 0.5.19
22 |
23 | * Fix detection of `c2hs` and `hsc2hs` files
24 |
25 | ## 0.5.15
26 |
27 | * Add support for RAML
28 |
29 | ## 0.5.14
30 |
31 | * Add `--no-style` flag to suppress CSS styles from HTML output
32 |
33 | ## 0.5.14
34 |
35 | * More compact HTML output
36 | * Remove unused language support
37 |
38 | ## 0.5.13
39 |
40 | * Add support for Agda libraries
41 | * Add support for Cedille
42 | * Alphabetize 'Carp' correctly
43 |
44 | ## 0.5.12
45 |
46 | * Fix bug in `fish` printing
47 | * Add support for Squirrel
48 | * Add support for Io
49 | * Fix Chapel printing bug
50 |
51 | ## 0.5.11
52 |
53 | * Add support for Lean
54 | * Tiny performance improvements
55 | * Fix bug in command-line parser
56 | * Exclude `build` directory for Blodwen
57 | * Detect `R` shebangs
58 |
59 | ## 0.5.10
60 |
61 | * Add HTML output flag `--html`
62 | * Re-categorize some theorem provers
63 |
64 | ## 0.5.8
65 |
66 | * Fix performance issue by making some core functions call-by-reference
67 |
68 | ## 0.5.7
69 |
70 | * Add support for Nu
71 | * Add support for Haxe
72 | * Add support for Eiffel
73 | * Add support for TLA+
74 | * Minor bugfix
75 |
76 | ## 0.5.6
77 |
78 | * Add support for Apex
79 | * Add support for SAS
80 | * Fix typo
81 |
82 | ## 0.5.5
83 |
84 | * Add support for Cogent
85 | * Add support for Clean
86 | * Add support for Thrift
87 | * Add support for Vala
88 |
89 | ## 0.5.4
90 |
91 | * Add support for Oz, Zimpl, Volt, and Jai
92 | * Better fish detection
93 |
94 | ## 0.5.3
95 |
96 | * Add support for TypeScript, CoffeeScript, Red, Frege, Dart, Egison, Zig,
97 | SQL, Felix, and Q#.
98 | * Fix typo
99 |
100 | ## 0.5.2
101 |
102 | * Bug fixes
103 |
104 | ## 0.5.0
105 |
106 | * Add `-v`/`--verbose` flag for more detailed output
107 |
108 | ## 0.4.75
109 |
110 | * Fix FORTRAN comments
111 |
112 | ## 0.4.74
113 |
114 | * Add support for K
115 | * Fix minor bug with threading
116 |
117 | ## 0.4.73
118 |
119 | * Add support for Ragel
120 | * Add support for awk
121 | * Add support for sed
122 |
123 | ## 0.4.72
124 |
125 | * Add language support for Chapel
126 | * Add language support for Pascal
127 | * Improve detection of Haskell
128 |
129 | ## 0.4.70
130 |
131 | * Add language support for Scheme
132 |
--------------------------------------------------------------------------------
/atspkg.dhall:
--------------------------------------------------------------------------------
1 | let prelude =
2 | https://raw.githubusercontent.com/vmchale/atspkg/master/ats-pkg/dhall/atspkg-prelude.dhall sha256:69bdde38a8cc01c91a1808ca3f45c29fe754c9ac96e91e6abd785508466399b4
3 |
4 | in λ(cfg : { gc : Bool, cross : Bool, parallel : Bool, static : Bool }) →
5 | let deps = if cfg.parallel then [ "concurrency" ] else [] : List Text
6 |
7 | let staticFlag = if cfg.static then [ "-static" ] else [] : List Text
8 |
9 | let srcFile = if cfg.parallel then "polyglot" else "compat"
10 |
11 | in prelude.compilerMod
12 | prelude.gcc
13 | ( prelude.default
14 | ⫽ { bin =
15 | [ prelude.bin
16 | ⫽ { src = "src/${srcFile}.dats"
17 | , target = "${prelude.atsProject}/poly"
18 | , gcBin = cfg.gc
19 | , libs = [ "pthread" ]
20 | }
21 | ]
22 | , test =
23 | [ prelude.bin
24 | ⫽ { src = "test/test.dats"
25 | , target = "${prelude.atsProject}/test"
26 | , gcBin = cfg.gc
27 | , libs = [ "pthread" ]
28 | }
29 | ]
30 | , bench =
31 | [ prelude.bin
32 | ⫽ { src = "test/bench.dats"
33 | , target = "${prelude.atsProject}/bench"
34 | , gcBin = cfg.gc
35 | , libs = [ "pthread" ]
36 | }
37 | ]
38 | , man = Some "man/poly.md"
39 | , completions = Some "compleat/poly.usage"
40 | , dependencies =
41 | prelude.mapPlainDeps deps
42 | # [ prelude.upperDeps
43 | { name = "specats", version = [ 0, 2, 3 ] }
44 | , prelude.lowerDeps
45 | { name = "edit-distance", version = [ 0, 4, 0 ] }
46 | , prelude.plainDeps "ats-bench"
47 | ]
48 | , clib =
49 | if cfg.gc
50 | then [ prelude.upperDeps
51 | { name = "gc", version = [ 7, 6, 8 ] }
52 | ]
53 | else prelude.mapPlainDeps ([] : List Text)
54 | , cflags = [ "-I", "include", "-I", "." ] # staticFlag
55 | , compiler = [ 0, 4, 2 ]
56 | , version = [ 0, 4, 2 ]
57 | , debPkg =
58 | prelude.mkDeb
59 | ( prelude.debian "polyglot"
60 | ⫽ { version = [ 0, 5, 29 ]
61 | , maintainer = "Vanessa McHale "
62 | , description = "Determine project contents"
63 | , manpage = Some "man/poly.1"
64 | , binaries = [ "${prelude.atsProject}/poly" ]
65 | }
66 | )
67 | }
68 | )
69 |
--------------------------------------------------------------------------------
/DATS/utils.dats:
--------------------------------------------------------------------------------
1 | staload "SATS/filetype.sats"
2 | staload "SATS/utils.sats"
3 |
4 | implement add_results (x, y) =
5 | let
6 | var next = @{ lines = x.lines + y.lines
7 | , blanks = x.blanks + y.blanks
8 | , comments = x.comments + y.comments
9 | , files = x.files + y.files
10 | }
11 | in
12 | next
13 | end
14 |
15 | implement eq_pl_type (x, y) =
16 | case- (x, y) of
17 | | (happy (_), happy (_)) => true
18 | | (yacc (_), yacc (_)) => true
19 | | (coq (_), coq (_)) => true
20 | | (verilog (_), verilog (_)) => true
21 |
22 | implement free_pl (pl) =
23 | case+ pl of
24 | | ~unknown _ => ()
25 | | ~rust _ => ()
26 | | ~haskell _ => ()
27 | | ~perl _ => ()
28 | | ~lucius _ => ()
29 | | ~cassius _ => ()
30 | | ~hamlet _ => ()
31 | | ~julius _ => ()
32 | | ~bash _ => ()
33 | | ~dash _ => ()
34 | | ~coq _ => ()
35 | | ~justfile _ => ()
36 | | ~makefile _ => ()
37 | | ~yaml _ => ()
38 | | ~toml _ => ()
39 | | ~dhall _ => ()
40 | | ~ipkg _ => ()
41 | | ~ion _ => ()
42 | | ~mercury _ => ()
43 | | ~yacc _ => ()
44 | | ~lex _ => ()
45 | | ~r _ => ()
46 | | ~c _ => ()
47 | | ~cpp _ => ()
48 | | ~lua _ => ()
49 | | ~lalrpop _ => ()
50 | | ~header _ => ()
51 | | ~sixten _ => ()
52 | | ~java _ => ()
53 | | ~scala _ => ()
54 | | ~elixir _ => ()
55 | | ~erlang _ => ()
56 | | ~happy _ => ()
57 | | ~alex _ => ()
58 | | ~go _ => ()
59 | | ~html _ => ()
60 | | ~css _ => ()
61 | | ~scss _ => ()
62 | | ~brainfuck _ => ()
63 | | ~ruby _ => ()
64 | | ~julia _ => ()
65 | | ~elm _ => ()
66 | | ~purescript _ => ()
67 | | ~vimscript _ => ()
68 | | ~ocaml _ => ()
69 | | ~madlang _ => ()
70 | | ~agda _ => ()
71 | | ~idris _ => ()
72 | | ~futhark _ => ()
73 | | ~ats _ => ()
74 | | ~tex _ => ()
75 | | ~cabal _ => ()
76 | | ~cobol _ => ()
77 | | ~tcl _ => ()
78 | | ~verilog _ => ()
79 | | ~vhdl _ => ()
80 | | ~markdown _ => ()
81 | | ~python _ => ()
82 | | ~pony _ => ()
83 | | ~jupyter _ => ()
84 | | ~clojure _ => ()
85 | | ~cabal_project _ => ()
86 | | ~assembly _ => ()
87 | | ~nix _ => ()
88 | | ~php _ => ()
89 | | ~javascript _ => ()
90 | | ~kotlin _ => ()
91 | | ~fsharp _ => ()
92 | | ~fortran _ => ()
93 | | ~swift _ => ()
94 | | ~csharp _ => ()
95 | | ~nim _ => ()
96 | | ~cpp_header _ => ()
97 | | ~elisp _ => ()
98 | | ~plaintext _ => ()
99 | | ~rakefile _ => ()
100 | | ~llvm _ => ()
101 | | ~autoconf _ => ()
102 | | ~batch _ => ()
103 | | ~powershell _ => ()
104 | | ~m4 _ => ()
105 | | ~objective_c _ => ()
106 | | ~automake _ => ()
107 | | ~carp _ => ()
108 | | ~shen _ => ()
109 | | ~greencard _ => ()
110 | | ~cmm _ => ()
111 | | ~fluid _ => ()
112 | | ~plutus _ => ()
113 | | ~j _ => ()
114 | | ~blodwen _ => ()
115 | | ~crystal _ => ()
116 | | ~racket _ => ()
117 | | ~ada _ => ()
118 | | ~sml _ => ()
119 | | ~isabelle _ => ()
120 | | ~fstar _ => ()
121 | | ~d _ => ()
122 | | ~factor _ => ()
123 | | ~scheme _ => ()
124 | | ~chapel _ => ()
125 | | ~pascal _ => ()
126 | | ~ragel _ => ()
127 | | ~xml _ => ()
128 | | ~awk _ => ()
129 | | ~sed _ => ()
130 | | ~k _ => ()
131 | | ~typescript _ => ()
132 | | ~coffeescript _ => ()
133 | | ~red _ => ()
134 | | ~fish _ => ()
135 | | ~vb _ => ()
136 | | ~frege _ => ()
137 | | ~dart _ => ()
138 | | ~solidity _ => ()
139 | | ~egison _ => ()
140 | | ~zig _ => ()
141 | | ~sql _ => ()
142 | | ~felix _ => ()
143 | | ~qsharp _ => ()
144 | | ~oz _ => ()
145 | | ~jai _ => ()
146 | | ~zimpl _ => ()
147 | | ~volt _ => ()
148 | | ~cogent _ => ()
149 | | ~clean _ => ()
150 | | ~thrift _ => ()
151 | | ~vala _ => ()
152 | | ~apex _ => ()
153 | | ~sas _ => ()
154 | | ~nu _ => ()
155 | | ~haxe _ => ()
156 | | ~eiffel _ => ()
157 | | ~tla _ => ()
158 | | ~lean _ => ()
159 | | ~io _ => ()
160 | | ~squirrel _ => ()
161 | | ~agdalib _ => ()
162 | | ~cedille _ => ()
163 | | ~raml _ => ()
164 | | ~scribble _ => ()
165 | | ~bibtex _ => ()
166 | | ~csv _ => ()
167 | | ~terraform _ => ()
168 | | ~org _ => ()
169 | | ~vagrantfile _ => ()
170 | | ~glsl _ => ()
171 | | ~dickinson _ => ()
172 | | ~mirth _ => ()
173 | | ~flix _ => ()
174 | | ~jac _ => ()
175 | | ~gdb _ => ()
176 | | ~bqn _ => ()
177 |
--------------------------------------------------------------------------------
/test/data/cli.dats:
--------------------------------------------------------------------------------
1 | #include "share/atspre_staload.hats"
2 |
3 | staload "libats/ML/SATS/string.sats"
4 | staload "libats/ML/DATS/string.dats"
5 |
6 | // Type for the parsed command-line arguments.
7 | vtypedef command_line = @{ version = bool
8 | , help = bool
9 | , no_table = bool
10 | , no_parallel = bool
11 | , excludes = [m:nat] list(string, m)
12 | , includes = [m:nat] list(string, m)
13 | }
14 |
15 | fun version() : void =
16 | println!("polygot version 0.3.39\nCopyright (c) 2018 Vanessa McHale")
17 |
18 | fun help() : void =
19 | print("polyglot - Count lines of code quickly.
20 | \33[36mUSAGE:\33[0m poly [DIRECTORY] ... [OPTION] ...
21 | \33[36mFLAGS:\33[0m
22 | -V, --version show version information
23 | -h, --help display this help and exit
24 | -e, --exclude exclude a directory
25 | -p, --no-parallel do not execute in parallel
26 | -t, --no-table display results in alternate format
27 |
28 | When no directory is provided poly will execute in the
29 | current directory.
30 |
31 | Bug reports and updates: github.com/vmchale/polyglot\n")
32 |
33 | fun is_flag(s : string) : bool =
34 | string_is_prefix("-", s)
35 |
36 | fn bad_exclude(s : string) : void =
37 | (println!("\33[31mError:\33[0m flag "
38 | + s
39 | + " must be followed by an argument and must occur alone") ; exit(0) ; ())
40 |
41 | fun process_short { s : int | s > 0 }(s : string(s), acc : command_line) : command_line =
42 | let
43 | var str = string_make_substring(s, i2sz(0), i2sz(1))
44 | var acc_r = ref(acc)
45 | val () = case+ str of
46 | | "h" => acc_r->help := true
47 | | "p" => acc_r->no_parallel := true
48 | | "t" => acc_r->no_table := true
49 | | "e" => bad_exclude(s)
50 | | "V" => acc_r->version := true
51 | | "-" => ()
52 | | _ => (println!("\33[31mError:\33[0m flag '" + s + "' not recognized") ; exit(0) ; ())
53 |
54 | fn witness(s : string) : [ n : nat | n > 0 ] string(n) =
55 | $UN.cast(s)
56 |
57 | val inter = !acc_r
58 | in
59 | if length(s) > 1 then
60 | process_short(witness(string_make_substring(s, i2sz(1), length(s))), inter)
61 | else
62 | inter
63 | end
64 |
65 | fun process(s : string, acc : command_line, is_first : bool) : command_line =
66 | let
67 | fn witness(s : string) : [ s : nat | s > 0 ] string(s) =
68 | $UN.cast(s)
69 |
70 | var acc_r = ref(acc)
71 | val () = if is_flag(s) then
72 | case+ s of
73 | | "--help" => acc_r->help := true
74 | | "-h" => acc_r->help := true
75 | | "--no-table" => if not(acc.no_table) then
76 | acc_r->no_table := true
77 | else
78 | (println!("\33[31mError:\33[0m flag " + s + " cannot appear twice") ; exit(0) ; ())
79 | | "-t" => if not(acc.no_table) then
80 | acc_r->no_table := true
81 | else
82 | (println!("\33[31mError:\33[0m flag " + s + " cannot appear twice") ; exit(0) ; ())
83 | | "--no-parallel" => acc_r->no_parallel := true
84 | | "-p" => acc_r->no_parallel := true
85 | | "--version" => acc_r->version := true
86 | | "-V" => acc_r->version := true
87 | | "-e" => bad_exclude(s)
88 | | "--exclude" => bad_exclude(s)
89 | | _ => let
90 | val new_acc = process_short(witness(s), acc)
91 | val _ = acc_r->help := new_acc.help
92 | val _ = acc_r->no_parallel := new_acc.no_parallel
93 | val _ = acc_r->version := new_acc.version
94 | val _ = acc_r->no_table := new_acc.no_table
95 | in
96 | ()
97 | end
98 | else
99 | if not(is_first) then
100 | acc_r->includes := list_cons(s, acc.includes)
101 | else
102 | ()
103 | in
104 | !acc_r
105 | end
106 |
107 | fun process_excludes(s : string, acc : command_line) : command_line =
108 | let
109 | var acc_r = ref(acc)
110 | val () = if is_flag(s) then
111 | ( println!("\33[31mError:\33[0m flag " + s + " found where a directory name was expected")
112 | ; exit(0)
113 | ; ()
114 | )
115 | else
116 | acc_r->excludes := list_cons(s, acc.excludes)
117 | in
118 | !acc_r
119 | end
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Features
2 | - [ ] Generate build reports in the format of `cloc` (`gocloc
3 | --output-type=sloccount .`)
4 | - [ ] Split on lines with `memchr` and then count comments?
5 | - [ ] `.poly.dhall` project file?
6 | - [ ] per-file output like `tokei`/`loc`
7 | - [ ] parse directories on the command line starting with a `-` by using escapes
8 | - [ ] detect documentation comments
9 | - [ ] feature to use data from quasi-quotes (e.g. haskell)
10 | - [ ] block comments
11 | - [ ] Allow generation of HTML tables from output.
12 | - [ ] JSON output? Or alternately some other form of output?
13 | - [ ] HTML pretty-printer would be nice.
14 | - [ ] Allow/disallow symlinks
15 | - [ ] Library for semantic analysis?
16 | - [ ] Avoid overlaps when subdirectories passed as arguments?
17 | - [ ] Make intelligent guesses also work w/ `thefuck`? Write python idk.
18 | - [ ] Point to github URL?
19 | # Performance
20 | - [ ] Use GCC 9.1.0
21 | - [ ] https://lawsofux.com/doherty-threshold.html
22 | - [x] parallelism
23 | - [ ] better parallelism
24 | - [ ] Use `memcmp` for string/comment comparisons? (`strcmp`)
25 | - [ ] Also filter by length?
26 | - [ ] Potentially useful in the `ifcase` things...
27 | - [ ] make sure everything is tail recursive
28 | - [ ] get rid of GC (?)
29 | - [ ] Use more linear types
30 | - [ ] Write my own dirstream??
31 | - [ ] Look at https://github.com/llogiq/bytecount
32 | - [ ] count lines with SIMD - not just search for stuff
33 | - [ ] also maybe https://github.com/boyerjohn/rapidstring
34 | - [ ] Use `strpbrk` during parsing comments?
35 | - [ ] Benchmark memory footprint!
36 | - [ ] `check_keywords` is very inefficient
37 | # Distribution
38 | - [x] Make a debianization?
39 | - [ ] Add to debian
40 | - [ ] Package `compleat`
41 | - [ ] Compress via travis
42 | - [ ] `pkg-config` stuff for library
43 | # CI
44 | - [ ] Figure out how to download/unpack/etc. https://github.com/jgm/pandoc/releases/download/2.2.3.2/pandoc-2.2.3.2-linux.tar.gz
45 | # Portability
46 | - [ ] Figure out Windows (?)
47 | - [ ] Cross-compilation?
48 | # Bugs
49 | - [ ] Warnings should not display in color when `-c` is passed
50 | - [ ] Warn on nonexistent directory
51 | - [ ] Fix infinite loop in `poly /usr/local/mercury-14.01.1/`
52 | - [ ] Fix gcc/clang build
53 | - [ ] Seems to be due to `nproc`
54 | - [ ] Post to ATS mailing list?
55 | - [ ] Use as a test case: git@github.com:kovidgoyal/kitty.git
56 | - [ ] Use as a test case: qt5-everywhere
57 | - [ ] Fortran `c` comments
58 | - [ ] Allow multiple syntaxes for comments, e.g. `#` for assembly
59 | - [ ] First comment in a file is ignored
60 | - [ ] Handle `sed`-style multiline comments
61 | - [ ] Comments on borders between buffers
62 | - [ ] Is `.ac` always M4?
63 | - [ ] `.bf` could be befunge
64 | - [ ] Handle dhall files w/ no extension?
65 | - [ ] doesn't disambiguate objective C/C headers
66 | - [ ] `ncpu` goes insane for some reason
67 | - [ ] `poly -t README.md` adds spurious line of output
68 | - [ ] handle `\-dir` for directories
69 | - [ ] Allow three characters for comments (J's `NB.`)
70 | - [ ] Fix library linking for distributable Mac binaries
71 | - [ ] Bug w/ comments: https://www.reddit.com/r/rust/comments/99e4tq/reading_files_quickly_in_rust/e4nh5nf
72 | # Code Maintenance
73 | - [ ] Flag for printing debug info?
74 | - [ ] Library for this
75 | - [ ] Library stanza & Haskell bindings
76 | - [ ] Executable that depends on the library
77 | - [ ] linear types to ensure each field gets printed at the end?
78 | - [ ] or alternately a macro
79 | - [ ] Use a `Makefile` rather than a `Justfile`
80 | # Libraries
81 | - [ ] Dhall library for ATS (or sufficient bindings)
82 | - [ ] Library for `.gitignore` files (and `.ignore` or `_darcs/boring` files)
83 | - [ ] Parallel directory traversal (templates?)
84 | - [ ] Library for cross-platform directory access?
85 | # Documentation
86 | - [ ] Benchmark against sloccount?
87 | - [ ] Document build/configuration options
88 | - [ ] Compare to http://hackage.haskell.org/package/cantor ?
89 | # Research
90 | - [ ] Learn about `memcmp` and `memcpy`
91 | - [ ] Look into state machines and how to actually make a parser
92 | - [ ] Look into parallel directory traversals & data structures for such
93 | - [ ] Atomics?? See what I can write for atomics in ATS
94 | - [ ] Find out what mutexes/spinlocks do
95 | # Build Tooling
96 | - [ ] Auto-generate functions related to file types?
97 | ## Heuristics
98 | ### Heuristics for determining file type:
99 | - [ ] parent directory (`.cargo/config`)
100 | - [ ] modeline
101 | - [ ] `.gitattributes`
102 | - [ ] `.poly.dhall` project file
103 | ### Heuristics for determining file relevance:
104 | - [ ] `.gitignore`/darcs boringfile/`.ignore` file
105 | - [ ] `.gitattributes`
106 | - [ ] `.poly.dhall` project file
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # polyglot
2 |
3 | [](https://travis-ci.org/vmchale/polyglot)
4 |
5 | `poly` is a command-line tool that determines project contents.
6 | The goal is to able to point it to any directory and get an accurate,
7 | complete, and informative summary of its contents.
8 |
9 |
10 |
11 | It also has the secondary goal of advancing the state-of-the art for ATS, by
12 | writing practical, distributable software and supporting tooling.
13 |
14 | ## Pitch
15 |
16 | Reasons to use polyglot:
17 |
18 | * Accurate: won't confuse Coq and Verilog
19 | * Fast: polyglot is faster than all other tools
20 | * Pretty: magenta output
21 |
22 | Reasons not to use polyglot:
23 |
24 | * Written in ATS
25 | * Best on Linux
26 | * No regex-based exclusions
27 | * Doesn't read `.gitignore` &c.
28 | * Doesn't count block comments
29 | * Multiline string
30 | [bug](https://github.com/Aaronepower/tokei/blob/master/COMPARISON.md#Accuracy).
31 |
32 | ### Benchmarks
33 |
34 | On the Rust repo:
35 |
36 |
37 |
38 | | Tool |
39 | Language |
40 | Time |
41 |
42 |
43 | polyglot |
44 | ATS |
45 | 134.6 ms |
46 |
47 |
48 | loc |
49 | Rust |
50 | 139.6 ms |
51 |
52 |
53 | scc |
54 | Go |
55 | 225.4 ms |
56 |
57 |
58 | tokei |
59 | Rust |
60 | 262.6 ms |
61 |
62 |
63 | gocloc |
64 | Go |
65 | 923.9 ms |
66 |
67 |
68 | cloc |
69 | Perl |
70 | 5.610 s |
71 |
72 |
73 | enry |
74 | Go |
75 | 6.926 s |
76 |
77 |
78 | linguist |
79 | Ruby |
80 | 20.16 s |
81 |
82 |
83 |
84 | For more extensive benchmarks, see my [blog post](http://blog.vmchale.com/article/polyglot-comparisons)
85 | with some additional data.
86 |
87 | ### Heuristics
88 |
89 | Polyglot distinguishes itself from `tokei`, `gocloc`, and `loc` by being able to disambiguate file names.
90 | Thus, `poly` will not confuse Happy for Yacc (for instance).
91 |
92 | ## Installation
93 |
94 | ### From a Script
95 |
96 | The easiest way to install is to use the installation script, like so:
97 |
98 | ```bash
99 | curl -sSl https://raw.githubusercontent.com/vmchale/polyglot/master/bash/install.sh | sh -s
100 | ```
101 |
102 | You can optionally install [compleat](https://github.com/mbrubeck/compleat) for
103 | shell completions as well.
104 |
105 | ### Vim Plugin
106 |
107 | There is a [vim plugin](https://github.com/vmchale/polyglot-vim) available which
108 | can count lines of code in a project.
109 |
110 | ### Documentation
111 |
112 | You can view manpages for `poly` with
113 |
114 | ```
115 | man poly
116 | ```
117 |
118 | ## Building for Hacking
119 |
120 | You can install [ats-pkg](http://hackage.haskell.org/package/ats-pkg)
121 | with
122 |
123 | ```bash
124 | curl -sSl https://raw.githubusercontent.com/vmchale/atspkg/master/bash/install.sh | sh -s
125 | ```
126 |
127 | And then build `poly` with
128 |
129 | ```bash
130 | git clone git@github.com:vmchale/polyglot.git
131 | cd polyglot
132 | atspkg build --pkg-args './gc.dhall'
133 | ```
134 |
135 | This will put a binary at `target/poly`.
136 |
137 | If you are on Mac, replace the last line with
138 |
139 | ```bash
140 | atspkg build --pkg-args './mac.dhall'
141 | ```
142 |
143 | ### Testing
144 |
145 | To run the test suite
146 |
147 | ```bash
148 | atspkg test --pkg-args './gc.dhall'
149 | ```
150 |
151 | ## Languages
152 |
153 | For languages already supported, see
154 | [LANGUAGES.md](https://github.com/vmchale/polyglot/blob/master/LANGUAGES.md)
155 |
156 | ## Contents
157 |
158 | ```
159 | -------------------------------------------------------------------------------
160 | Language Files Lines Code Comments Blanks
161 | -------------------------------------------------------------------------------
162 | ATS 17 3794 3626 41 127
163 | C 1 24 22 0 2
164 | C Header 1 43 35 0 8
165 | Dash 5 144 110 8 26
166 | Dhall 5 93 83 0 10
167 | Markdown 6 938 813 0 125
168 | TOML 1 3 3 0 0
169 | YAML 1 58 52 0 6
170 | -------------------------------------------------------------------------------
171 | Total 37 5097 4744 49 304
172 | -------------------------------------------------------------------------------
173 | ```
174 |
--------------------------------------------------------------------------------
/test/data/Coq.v:
--------------------------------------------------------------------------------
1 | (************************************************************************)
2 | (* v * The Coq Proof Assistant / The Coq Development Team *)
3 | (* P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P.
26 | Proof.
27 | intros H1 H2 H3.
28 | destruct (n ?= m); auto.
29 | Defined.
30 |
31 | Lemma Zcompare_rec (P:Set) (n m:Z) :
32 | ((n ?= m) = Eq -> P) -> ((n ?= m) = Lt -> P) -> ((n ?= m) = Gt -> P) -> P.
33 | Proof. apply Zcompare_rect. Defined.
34 |
35 | Notation Z_eq_dec := Z.eq_dec (compat "8.3").
36 |
37 | Section decidability.
38 |
39 | Variables x y : Z.
40 |
41 | (** * Decidability of order on binary integers *)
42 |
43 | Definition Z_lt_dec : {x < y} + {~ x < y}.
44 | Proof.
45 | unfold Z.lt; case Z.compare; (now left) || (now right).
46 | Defined.
47 |
48 | Definition Z_le_dec : {x <= y} + {~ x <= y}.
49 | Proof.
50 | unfold Z.le; case Z.compare; (now left) || (right; tauto).
51 | Defined.
52 |
53 | Definition Z_gt_dec : {x > y} + {~ x > y}.
54 | Proof.
55 | unfold Z.gt; case Z.compare; (now left) || (now right).
56 | Defined.
57 |
58 | Definition Z_ge_dec : {x >= y} + {~ x >= y}.
59 | Proof.
60 | unfold Z.ge; case Z.compare; (now left) || (right; tauto).
61 | Defined.
62 |
63 | Definition Z_lt_ge_dec : {x < y} + {x >= y}.
64 | Proof.
65 | exact Z_lt_dec.
66 | Defined.
67 |
68 | Lemma Z_lt_le_dec : {x < y} + {y <= x}.
69 | Proof.
70 | elim Z_lt_ge_dec.
71 | * now left.
72 | * right; now apply Z.ge_le.
73 | Defined.
74 |
75 | Definition Z_le_gt_dec : {x <= y} + {x > y}.
76 | Proof.
77 | elim Z_le_dec; auto with arith.
78 | intro. right. Z.swap_greater. now apply Z.nle_gt.
79 | Defined.
80 |
81 | Definition Z_gt_le_dec : {x > y} + {x <= y}.
82 | Proof.
83 | exact Z_gt_dec.
84 | Defined.
85 |
86 | Definition Z_ge_lt_dec : {x >= y} + {x < y}.
87 | Proof.
88 | elim Z_ge_dec; auto with arith.
89 | intro. right. Z.swap_greater. now apply Z.lt_nge.
90 | Defined.
91 |
92 | Definition Z_le_lt_eq_dec : x <= y -> {x < y} + {x = y}.
93 | Proof.
94 | intro H.
95 | apply Zcompare_rec with (n := x) (m := y).
96 | intro. right. elim (Z.compare_eq_iff x y); auto with arith.
97 | intro. left. elim (Z.compare_eq_iff x y); auto with arith.
98 | intro H1. absurd (x > y); auto with arith.
99 | Defined.
100 |
101 | End decidability.
102 |
103 | (** * Cotransitivity of order on binary integers *)
104 |
105 | Lemma Zlt_cotrans : forall n m:Z, n < m -> forall p:Z, {n < p} + {p < m}.
106 | Proof.
107 | intros x y H z.
108 | case (Z_lt_ge_dec x z).
109 | intro.
110 | left.
111 | assumption.
112 | intro.
113 | right.
114 | apply Z.le_lt_trans with (m := x).
115 | apply Z.ge_le.
116 | assumption.
117 | assumption.
118 | Defined.
119 |
120 | Lemma Zlt_cotrans_pos : forall n m:Z, 0 < n + m -> {0 < n} + {0 < m}.
121 | Proof.
122 | intros x y H.
123 | case (Zlt_cotrans 0 (x + y) H x).
124 | - now left.
125 | - right.
126 | apply Z.add_lt_mono_l with (p := x).
127 | now rewrite Z.add_0_r.
128 | Defined.
129 |
130 | Lemma Zlt_cotrans_neg : forall n m:Z, n + m < 0 -> {n < 0} + {m < 0}.
131 | Proof.
132 | intros x y H; case (Zlt_cotrans (x + y) 0 H x); intro Hxy;
133 | [ right; apply Z.add_lt_mono_l with (p := x); rewrite Z.add_0_r | left ];
134 | assumption.
135 | Defined.
136 |
137 | Lemma not_Zeq_inf : forall n m:Z, n <> m -> {n < m} + {m < n}.
138 | Proof.
139 | intros x y H.
140 | case Z_lt_ge_dec with x y.
141 | intro.
142 | left.
143 | assumption.
144 | intro H0.
145 | generalize (Z.ge_le _ _ H0).
146 | intro.
147 | case (Z_le_lt_eq_dec _ _ H1).
148 | intro.
149 | right.
150 | assumption.
151 | intro.
152 | apply False_rec.
153 | apply H.
154 | symmetry .
155 | assumption.
156 | Defined.
157 |
158 | Lemma Z_dec : forall n m:Z, {n < m} + {n > m} + {n = m}.
159 | Proof.
160 | intros x y.
161 | case (Z_lt_ge_dec x y).
162 | intro H.
163 | left.
164 | left.
165 | assumption.
166 | intro H.
167 | generalize (Z.ge_le _ _ H).
168 | intro H0.
169 | case (Z_le_lt_eq_dec y x H0).
170 | intro H1.
171 | left.
172 | right.
173 | apply Z.lt_gt.
174 | assumption.
175 | intro.
176 | right.
177 | symmetry .
178 | assumption.
179 | Defined.
180 |
181 |
182 | Lemma Z_dec' : forall n m:Z, {n < m} + {m < n} + {n = m}.
183 | Proof.
184 | intros x y.
185 | case (Z.eq_dec x y); intro H;
186 | [ right; assumption | left; apply (not_Zeq_inf _ _ H) ].
187 | Defined.
188 |
189 | (* begin hide *)
190 | (* To deprecate ? *)
191 | Corollary Z_zerop : forall x:Z, {x = 0} + {x <> 0}.
192 | Proof.
193 | exact (fun x:Z => Z.eq_dec x 0).
194 | Defined.
195 |
196 | Corollary Z_notzerop : forall (x:Z), {x <> 0} + {x = 0}.
197 | Proof (fun x => sumbool_not _ _ (Z_zerop x)).
198 |
199 | Corollary Z_noteq_dec : forall (x y:Z), {x <> y} + {x = y}.
200 | Proof (fun x y => sumbool_not _ _ (Z.eq_dec x y)).
201 | (* end hide *)
202 |
--------------------------------------------------------------------------------
/DATS/count-loop.dats:
--------------------------------------------------------------------------------
1 | // adapted from the book. You can find the original here:
2 | // https://github.com/githwxi/ATS-Postiats/blob/master/doc/EXAMPLE/MISC/wclines.dats
3 | staload "SATS/utils.sats"
4 | staload "SATS/filetype.sats"
5 | staload "SATS/error.sats"
6 | staload "prelude/SATS/pointer.sats"
7 | staload "libats/libc/SATS/stdio.sats"
8 | staload UN = "prelude/SATS/unsafe.sats"
9 |
10 | // FIXME: changing BUFSZ changes the # of comments & the # of blanks
11 | #define BUFSZ (16*1024)
12 |
13 | %{#
14 | #include
15 | %}
16 |
17 | %{^
18 | #include
19 |
20 | bool is_link(char *path) {
21 | struct stat buf;
22 | int x;
23 | x = lstat(path, &buf);
24 | return S_ISLNK(buf.st_mode);
25 | }
26 | %}
27 |
28 | extern
29 | fn is_link(string) : bool =
30 | "mac#"
31 |
32 | extern
33 | fun memchr {l:addr}{m:nat}(pf : bytes_v(l, m) | p : ptr(l), c : char, size_t) :
34 | [ l0 : addr | l+m > l0 ] (bytes_v(l, l0-l), bytes_v(l0, l+m-l0)| ptr(l0)) =
35 | "mac#"
36 |
37 | fn freadc_ {l:addr}{ sz : nat | sz >= 1 }(pf : !bytes_v(l, sz)
38 | | inp : !FILEptr1, bufsize : size_t(sz), p : ptr(l), c : char) : size_t =
39 | let
40 | extern
41 | castfn as_fileref(x : !FILEptr1) :<> FILEref
42 |
43 | var n = $extfcall(size_t, "fread", p, sizeof, bufsize - 1, as_fileref(inp))
44 | val () = $UN.ptr0_set(ptr_add(p, n), c)
45 | in
46 | n
47 | end
48 |
49 | fn freadc {l:addr}(pf : !bytes_v(l, BUFSZ) | inp : !FILEptr1, p : ptr(l), c : char) : size_t =
50 | freadc_(pf | inp, i2sz(BUFSZ), p, c)
51 |
52 | vtypedef pair = @{ f = char, s = Option_vt(char) }
53 |
54 | fn get_chars {m:nat}(s : string(m)) : Option_vt(pair) =
55 | let
56 | var l = length(s)
57 | in
58 | ifcase
59 | | l >= 2 => let
60 | val p = @{ f = string_head(s), s = Some_vt(s[1]) }
61 | in
62 | Some_vt(p)
63 | end
64 | | l >= 1 => let
65 | val p = @{ f = string_head(s), s = None_vt }
66 | in
67 | Some_vt(p)
68 | end
69 | | _ => None_vt
70 | end
71 |
72 | // safely read bytes at a pointer
73 | fn read_bytes {l:addr}{ m : nat | m > 0 }(pf : !bytes_v(l, m) | p : ptr(l)) : char =
74 | $UN.ptr0_get(p)
75 |
76 | fn read_bytes_succ {l:addr}{ m : nat | m > 1 }(pf : !bytes_v(l, m) | p : ptr(l)) : char =
77 | $UN.ptr0_get(ptr_succ(p))
78 |
79 | fn compare_bytes {l:addr}{m:nat}(pf : !bytes_v(l, m) | p : ptr(l), comment : !Option_vt(pair)) : '(bool, bool) =
80 | let
81 | var match = lam@ (x : char, y : !Option_vt(char)) : bool =>
82 | case+ y of
83 | | Some_vt (z) => x = z
84 | | None_vt() => true
85 |
86 | // FIXME: this will fail if we have a comment at the boundaries.
87 | var s2 = $UN.ptr0_get(p)
88 | var b = s2 = '\n'
89 | var b2 = case+ comment of
90 | | None_vt() => false
91 | | Some_vt (p0) => let
92 | var s3 = $UN.ptr0_get(ptr_succ(p))
93 | in
94 | s2 = p0.f && match(s3, p0.s)
95 | end
96 | in
97 | '(b, b2)
98 | end
99 |
100 | // TODO: try to do call-by-reference but also stack allocate?
101 | // this uses call-by-reference to go extra fast
102 | fun wclbuf {l:addr}{n:nat}{l1:addr}( pf : !bytes_v(l, n) | p : ptr(l)
103 | , pz : ptr(l1)
104 | , res : file
105 | , comment : !Option_vt(pair)
106 | , ret : &file? >> file
107 | ) : void =
108 | let
109 | val (pf1, pf2 | p2) = memchr(pf | p, '\n', i2sz(BUFSZ))
110 | var match_acc_file = lam@ (b : bool, b2 : bool) : file =>
111 | case+ (b, b2) of
112 | | (true, true) => @{ files = 0, blanks = 1, comments = 1, lines = 1 }
113 | | (true, false) => @{ files = 0, blanks = 1, comments = 0, lines = 1 }
114 | | (false, true) => @{ files = 0, blanks = 0, comments = 1, lines = 1 }
115 | | (false, false) => @{ files = 0, blanks = 0, comments = 0, lines = 1 }
116 | in
117 | if p2 < pz then
118 | let
119 | prval (pf21, pf22) = array_v_uncons(pf2)
120 |
121 | // FIXME: this will always ignore a comment in the first line of a file...
122 | val '(cmp1, cmp2) = compare_bytes(pf22 | ptr_succ(p2), comment)
123 | var acc_file = match_acc_file(cmp1, cmp2)
124 | val () = wclbuf(pf22 | ptr_succ(p2), pz, res + acc_file, comment, ret)
125 | prval () = pf2 := array_v_cons(pf21,pf22)
126 | prval () = pf := bytes_v_unsplit(pf1,pf2)
127 | in end
128 | else
129 | let
130 | prval () = pf := bytes_v_unsplit(pf1,pf2)
131 | in
132 | ret := res
133 | end
134 | end
135 |
136 | fn wclfil {l:addr}(pf : !bytes_v(l, BUFSZ) | inp : !FILEptr1, p : ptr(l), comment : !Option_vt(pair)) : file =
137 | let
138 | var acc_file = @{ files = 1, blanks = ~1, comments = 0, lines = 0 } : file
139 |
140 | fun loop(pf : !bytes_v(l, BUFSZ) | inp : !FILEptr1, p : ptr(l), res : file, comment : !Option_vt(pair)) : file =
141 | let
142 | var n = freadc(pf | inp, p, '\n')
143 | in
144 | if n > 0 then
145 | let
146 | extern
147 | castfn witness(x : size_t) :<> [m:nat] size_t(m)
148 |
149 | var pz = ptr_add(p, witness(n))
150 | var ret: file
151 | val () = wclbuf(pf | p, pz, res, comment, ret)
152 | in
153 | loop(pf | inp, p, ret, comment)
154 | end
155 | else
156 | let
157 | fn postproc(acc : file) : file =
158 | let
159 | var acc_r = ref(acc)
160 | val () = if acc.blanks = ~1 then
161 | acc_r -> blanks := 0
162 | else
163 | ()
164 | in
165 | !acc_r
166 | end
167 | in
168 | postproc(res)
169 | end
170 | end
171 | in
172 | loop(pf | inp, p, acc_file, comment)
173 | end
174 |
175 | fn clear_opt(x : Option_vt(char)) : void =
176 | case+ x of
177 | | ~None_vt() => ()
178 | | ~Some_vt (_) => ()
179 |
180 | overload free with clear_opt
181 |
182 | fn clear_function(x : Option_vt(pair)) : void =
183 | case+ x of
184 | | ~None_vt() => ()
185 | | ~Some_vt (x) => free(x.s)
186 |
187 | overload free with clear_function
188 |
189 | val empty_file: file = let
190 | var f = @{ files = 0, blanks = 0, comments = 0, lines = 0 } : file
191 | in
192 | f
193 | end
194 |
195 | fn count_char(s : string, comment : Option_vt(pair)) : file =
196 | let
197 | // TODO: use a dataview to make this safe??
198 | var inp = fopen(s, file_mode_r)
199 | in
200 | if FILEptr_is_null(inp) then
201 | let
202 | extern
203 | castfn fp_is_null { l : addr | l == null }{m:fm} (FILEptr(l,m)) :<> void
204 |
205 | val () = fp_is_null(inp)
206 | val () = bad_file(s)
207 | in
208 | (free(comment) ; empty_file)
209 | end
210 | else
211 | let
212 | // TODO: allocate once per thread
213 | val (pfat, pfgc | p) = malloc_gc(g1i2u(BUFSZ))
214 | prval () = pfat := b0ytes2bytes_v(pfat)
215 | var res = wclfil(pfat | inp, p, comment)
216 | val () = mfree_gc(pfat, pfgc | p)
217 | val () = fclose1_exn(inp)
218 | val () = free(comment)
219 | in
220 | res
221 | end
222 | end
223 |
224 | // This ensures safety.
225 | typedef small_string = [ m : nat | m <= 2 && m > 0 ] string(m)
226 |
227 | fn line_count_skip_links(s : string, pre : Option_vt(small_string)) : file =
228 | if is_link(s) then
229 | case+ pre of
230 | | ~Some_vt (_) => empty_file
231 | | ~None_vt() => empty_file
232 | else
233 | case+ pre of
234 | | ~Some_vt (x) => count_char(s, get_chars(x))
235 | | ~None_vt() => count_char(s, None_vt)
236 |
237 | fn line_count(s : string, pre : Option_vt(small_string)) : file =
238 | case+ pre of
239 | | ~Some_vt (x) => count_char(s, get_chars(x))
240 | | ~None_vt() => count_char(s, None_vt)
241 |
--------------------------------------------------------------------------------
/DATS/cli.dats:
--------------------------------------------------------------------------------
1 | staload "libats/ML/SATS/string.sats"
2 | staload _ = "libats/ML/DATS/string.dats"
3 | staload UN = "prelude/SATS/unsafe.sats"
4 | staload "SATS/error.sats"
5 | staload "$PATSHOMELOCS/edit-distance-0.5.0/SATS/edit-distance.sats"
6 |
7 | #include "DATS/version.dats"
8 |
9 | // Type for the parsed command-line arguments.
10 | vtypedef command_line = @{ version = bool
11 | , help = bool
12 | , no_table = bool
13 | , html = bool
14 | , no_style = bool
15 | , no_parallel = bool
16 | , no_colorize = bool
17 | , skip_links = bool
18 | , verbose = bool
19 | , excludes = [m:nat] list(string, m)
20 | , includes = [m:nat] list(string, m)
21 | }
22 |
23 | fn version() : void =
24 | {
25 | val () = println!("polygot version 0.5.29")
26 | val () = compiler_version()
27 | val () = libc_version()
28 | val () = println!("\nCopyright (c) 2018-2020 Vanessa McHale")
29 | }
30 |
31 | fn help() : void =
32 | print("polyglot - Count lines of code quickly.
33 | \33[36mUSAGE:\33[0m poly [DIRECTORY] ... [OPTION] ...
34 | \33[36mFLAGS:\33[0m
35 | -V, --version show version information
36 | -h, --help display this help and exit
37 | -e, --exclude exclude a directory
38 | -c, --no-color do not colorize output
39 | -p, --no-parallel do not execute in parallel
40 | -t, --no-table display results in alternate format
41 | -v, --verbose display per-file results
42 | --html dump HTML output
43 | -s, --no-style do not add CSS styles to HTML output
44 |
45 | When no directory is provided poly will execute in the
46 | current directory.
47 |
48 | Bug reports and updates: github.com/vmchale/polyglot\n")
49 |
50 | fn is_flag(s : string) : bool =
51 | string_is_prefix("-", s)
52 |
53 | fun process_short { s : int | s > 0 }(s : string(s), acc : command_line, fail : bool) : command_line =
54 | let
55 | var str = string_make_substring(s, i2sz(0), i2sz(1))
56 | var acc_r = ref(acc)
57 | val () = case+ str of
58 | | "h" => acc_r -> help := true
59 | | "p" => if not(acc.no_parallel) then
60 | acc_r -> no_parallel := true
61 | else
62 | bad_flag("-p")
63 | | "t" => if not(acc.no_table) then
64 | acc_r -> no_table := true
65 | else
66 | bad_flag("-t")
67 | | "e" => bad_exclude("-e")
68 | | "c" => acc_r -> no_colorize := true
69 | | "s" => acc_r -> no_style := true
70 | | "V" => acc_r -> version := true
71 | | "v" => acc_r -> verbose := true
72 | | "-" when fail => ( println!("\33[31mError:\33[0m failed to parse command-line flags. Try 'poly --help'.")
73 | ; exit(1)
74 | ; ()
75 | )
76 | | "-" => ()
77 | | _ => (println!("\33[31mError:\33[0m flag '" + s + "' not recognized") ; exit(1) ; ())
78 |
79 | extern
80 | castfn witness(s : string) : [ n : nat | n > 0 ] string(n)
81 |
82 | val inter = !acc_r
83 | in
84 | if length(s) > 1 then
85 | process_short(witness(string_make_substring(s, i2sz(1), length(s))), inter, true)
86 | else
87 | inter
88 | end
89 |
90 | fun process(s : string, acc : command_line, is_first : bool) : command_line =
91 | let
92 | extern
93 | castfn witness(s : string) : [ s : nat | s > 0 ] string(s)
94 |
95 | fn process(s : string) : string =
96 | case+ s of
97 | | ".." => "../"
98 | | _ => s
99 |
100 | fn unrecognized(s : string, flag : string) : void =
101 | (println!("\33[31mError:\33[0m flag '" + s + "' not recognized. Did you mean '" + flag + "'?") ; exit(1) ; ())
102 |
103 | var acc_r = ref(acc)
104 | val () = if is_flag(s) then
105 | case+ s of
106 | | "--help" => acc_r -> help := true
107 | | "-h" => acc_r -> help := true
108 | | "--html" => acc_r -> html := true
109 | | "--no-table" => if not(acc.no_table) then
110 | acc_r -> no_table := true
111 | else
112 | bad_flag(s)
113 | | "-t" => if not(acc.no_table) then
114 | acc_r -> no_table := true
115 | else
116 | bad_flag(s)
117 | | "--no-parallel" => if not(acc.no_parallel) then
118 | acc_r -> no_parallel := true
119 | else
120 | bad_flag(s)
121 | | "-p" => if not(acc.no_parallel) then
122 | acc_r -> no_parallel := true
123 | else
124 | bad_flag(s)
125 | | "--version" => acc_r -> version := true
126 | | "-V" => acc_r -> version := true
127 | | "--verbose" => acc_r -> verbose := true
128 | | "-v" => acc_r -> verbose := true
129 | | "--no-color" => acc_r -> no_colorize := true
130 | | "-c" => acc_r -> no_colorize := true
131 | | "--no-style" => acc_r -> no_style := true
132 | | "-s" => acc_r -> no_style := true
133 | | "-e" => bad_exclude(s)
134 | | "--exclude" => bad_exclude(s)
135 | | "-" => error_flag(s)
136 | | _ when levenshtein_(s, "--exclude") <= 2 => unrecognized(s, "--exclude")
137 | | _ when levenshtein_(s, "--help") <= 2 => unrecognized(s, "--help")
138 | | _ when levenshtein_(s, "--html") <= 2 => unrecognized(s, "--html")
139 | | _ when levenshtein_(s, "--no-parallel") <= 3 => unrecognized(s, "--no-parallel")
140 | | _ when levenshtein_(s, "--no-table") <= 3 => unrecognized(s, "--no-table")
141 | | _ when levenshtein_(s, "--no-style") <= 3 => unrecognized(s, "--no-style")
142 | | _ => let
143 | val new_acc = process_short(witness(s), acc, false)
144 | val _ = acc_r -> help := new_acc.help
145 | val _ = acc_r -> no_parallel := new_acc.no_parallel
146 | val _ = acc_r -> version := new_acc.version
147 | val _ = acc_r -> verbose := new_acc.verbose
148 | val _ = acc_r -> no_table := new_acc.no_table
149 | val _ = acc_r -> no_colorize := new_acc.no_colorize
150 | in
151 | ()
152 | end
153 | else
154 | if not(is_first) then
155 | acc_r -> includes := list_cons(process(s), acc.includes)
156 | else
157 | ()
158 | in
159 | !acc_r
160 | end
161 |
162 | fn process_excludes(s : string, acc : command_line) : command_line =
163 | let
164 | var acc_r = ref(acc)
165 | val () = if is_flag(s) then
166 | bad_directory(s)
167 | else
168 | acc_r -> excludes := list_cons(s, acc.excludes)
169 | in
170 | !acc_r
171 | end
172 |
173 | // TODO minor problem in how exclusions are handled with short flags
174 | fun get_cli { n : int | n >= 1 }{ m : nat | m < n } .. ( argc : int(n)
175 | , argv : !argv(n)
176 | , current : int(m)
177 | , prev_is_exclude : bool
178 | , acc : command_line
179 | ) : command_line =
180 | let
181 | var arg = argv[current]
182 | in
183 | if current < argc - 1 then
184 | if arg != "--exclude" && arg != "-e" then
185 | let
186 | val c = get_cli(argc, argv, current + 1, false, acc)
187 | in
188 | if prev_is_exclude && current != 0 then
189 | process_excludes(arg, c)
190 | else
191 | if current != 0 then
192 | process(arg, c, current = 0)
193 | else
194 | c
195 | end
196 | else
197 | let
198 | val c = get_cli(argc, argv, current + 1, true, acc)
199 | in
200 | c
201 | end
202 | else
203 | if prev_is_exclude then
204 | process_excludes(arg, acc)
205 | else
206 | process(arg, acc, current = 0)
207 | end
208 |
209 | fn check_cli(chk : command_line) : void =
210 | if chk.no_style && not(chk.html) then
211 | redundant_cli_flag()
212 | else
213 | ()
214 |
--------------------------------------------------------------------------------
/DATS/html.dats:
--------------------------------------------------------------------------------
1 | staload "SATS/filetype.sats"
2 | staload "SATS/error.sats"
3 | staload "libats/ML/SATS/string.sats"
4 | staload "libats/libc/SATS/stdio.sats"
5 |
6 | fn maybe_html_table(s : string, f : file) : string =
7 | let
8 | fn th(s : string) : string =
9 | "" + s + " | "
10 |
11 | var code = f.lines - f.comments - f.blanks
12 | in
13 | if f.files > 0 then
14 | ""
15 | + th(s)
16 | + th(tostring_int(f.files))
17 | + th(tostring_int(f.lines))
18 | + th(tostring_int(code))
19 | + th(tostring_int(f.comments))
20 | + th(tostring_int(f.blanks))
21 | + "
"
22 | else
23 | ""
24 | end
25 |
26 | fn make_table_columns(isc : source_contents) : string =
27 | let
28 | var table_header = "| Language | Files | Lines | Code | Comments | Blanks |
"
29 | var content = maybe_html_table("Ada", isc.ada)
30 | + maybe_html_table("Agda", isc.agda)
31 | + maybe_html_table("Agda library", isc.agdalib)
32 | + maybe_html_table("Alex", isc.alex)
33 | + maybe_html_table("Apex", isc.apex)
34 | + maybe_html_table("Assembly", isc.assembly)
35 | + maybe_html_table("ATS", isc.ats)
36 | + maybe_html_table("Awk", isc.awk)
37 | + maybe_html_table("Autoconf", isc.autoconf)
38 | + maybe_html_table("Automake", isc.automake)
39 | + maybe_html_table("Bash", isc.bash)
40 | + maybe_html_table("Batch", isc.batch)
41 | + maybe_html_table("Blodwen", isc.blodwen)
42 | + maybe_html_table("Brainfuck", isc.brainfuck)
43 | + maybe_html_table("C", isc.c)
44 | + maybe_html_table("C--", isc.cmm)
45 | + maybe_html_table("C++ Header", isc.cpp_header)
46 | + maybe_html_table("C++", isc.cpp)
47 | + maybe_html_table("C#", isc.csharp)
48 | + maybe_html_table("C Header", isc.header)
49 | + maybe_html_table("Cabal", isc.cabal)
50 | + maybe_html_table("Cabal Project", isc.cabal_project)
51 | + maybe_html_table("Carp", isc.carp)
52 | + maybe_html_table("Cassius", isc.cassius)
53 | + maybe_html_table("Cedille", isc.cedille)
54 | + maybe_html_table("Chapel", isc.chapel)
55 | + maybe_html_table("Clean", isc.clean)
56 | + maybe_html_table("COBOL", isc.cobol)
57 | + maybe_html_table("CoffeeScript", isc.coffeescript)
58 | + maybe_html_table("Cogent", isc.cogent)
59 | + maybe_html_table("Coq", isc.coq)
60 | + maybe_html_table("Crystal", isc.crystal)
61 | + maybe_html_table("CSS", isc.css)
62 | + maybe_html_table("CSV", isc.csv)
63 | + maybe_html_table("D", isc.d)
64 | + maybe_html_table("Dart", isc.dart)
65 | + maybe_html_table("Dash", isc.dash)
66 | + maybe_html_table("Dickinson", isc.dickinson)
67 | + maybe_html_table("Dhall", isc.dhall)
68 | + maybe_html_table("Egison", isc.egison)
69 | + maybe_html_table("Eiffel", isc.eiffel)
70 | + maybe_html_table("Elixir", isc.elixir)
71 | + maybe_html_table("Elm", isc.elm)
72 | + maybe_html_table("Emacs Lisp", isc.elisp)
73 | + maybe_html_table("Erlang", isc.erlang)
74 | + maybe_html_table("F#", isc.fsharp)
75 | + maybe_html_table("F*", isc.fstar)
76 | + maybe_html_table("Factor", isc.factor)
77 | + maybe_html_table("Felix", isc.felix)
78 | + maybe_html_table("Fish", isc.fish)
79 | + maybe_html_table("FLTK Data", isc.fluid)
80 | + maybe_html_table("Fortran", isc.fortran)
81 | + maybe_html_table("Frege", isc.frege)
82 | + maybe_html_table("Futhark", isc.futhark)
83 | + maybe_html_table("GLSL", isc.glsl)
84 | + maybe_html_table("Go", isc.go)
85 | + maybe_html_table("Greencard", isc.greencard)
86 | + maybe_html_table("Hamlet", isc.hamlet)
87 | + maybe_html_table("Happy", isc.happy)
88 | + maybe_html_table("Haskell", isc.haskell)
89 | + maybe_html_table("Haxe", isc.haxe)
90 | + maybe_html_table("HTML", isc.html)
91 | + maybe_html_table("Idris", isc.idris)
92 | + maybe_html_table("Io", isc.io)
93 | + maybe_html_table("iPKG", isc.ipkg)
94 | + maybe_html_table("Ion", isc.ion)
95 | + maybe_html_table("Isabelle", isc.isabelle)
96 | + maybe_html_table("J", isc.j)
97 | + maybe_html_table("Jai", isc.jai)
98 | + maybe_html_table("Java", isc.java)
99 | + maybe_html_table("JavaScript", isc.javascript)
100 | + maybe_html_table("Julius", isc.julius)
101 | + maybe_html_table("Julia", isc.julia)
102 | + maybe_html_table("Jupyter", isc.jupyter)
103 | + maybe_html_table("Justfile", isc.justfile)
104 | + maybe_html_table("K", isc.k)
105 | + maybe_html_table("Kotlin", isc.kotlin)
106 | + maybe_html_table("LALRPOP", isc.lalrpop)
107 | + maybe_html_table("Lean", isc.lean)
108 | + maybe_html_table("Lex", isc.lex)
109 | + maybe_html_table("LLVM", isc.llvm)
110 | + maybe_html_table("Lua", isc.lua)
111 | + maybe_html_table("Lucius", isc.lucius)
112 | + maybe_html_table("M4", isc.m4)
113 | + maybe_html_table("Madlang", isc.madlang)
114 | + maybe_html_table("Makefile", isc.makefile)
115 | + maybe_html_table("Markdown", isc.markdown)
116 | + maybe_html_table("Mercury", isc.mercury)
117 | + maybe_html_table("Mirth", isc.mirth)
118 | + maybe_html_table("Nim", isc.nim)
119 | + maybe_html_table("Nix", isc.nix)
120 | + maybe_html_table("Nu", isc.nu)
121 | + maybe_html_table("Objective C", isc.objective_c)
122 | + maybe_html_table("OCaml", isc.ocaml)
123 | + maybe_html_table("Org-mode", isc.org)
124 | + maybe_html_table("Oz", isc.oz)
125 | + maybe_html_table("Pascal", isc.pascal)
126 | + maybe_html_table("Perl", isc.perl)
127 | + maybe_html_table("PHP", isc.php)
128 | + maybe_html_table("Plaintext", isc.plaintext)
129 | + maybe_html_table("Plutus", isc.plutus)
130 | + maybe_html_table("PowerShell", isc.powershell)
131 | + maybe_html_table("Pony", isc.pony)
132 | + maybe_html_table("Python", isc.python)
133 | + maybe_html_table("PureScript", isc.purescript)
134 | + maybe_html_table("Q#", isc.qsharp)
135 | + maybe_html_table("R", isc.r)
136 | + maybe_html_table("Racket", isc.racket)
137 | + maybe_html_table("Ragel", isc.ragel)
138 | + maybe_html_table("Rakefile", isc.rakefile)
139 | + maybe_html_table("Red", isc.red)
140 | + maybe_html_table("Ruby", isc.ruby)
141 | + maybe_html_table("Rust", isc.rust)
142 | + maybe_html_table("SAS", isc.sas)
143 | + maybe_html_table("Scala", isc.scala)
144 | + maybe_html_table("Scheme", isc.scheme)
145 | + maybe_html_table("Scribble", isc.scribble)
146 | + maybe_html_table("SCSS", isc.scss)
147 | + maybe_html_table("Sed", isc.sed)
148 | + maybe_html_table("Shen", isc.shen)
149 | + maybe_html_table("Sixten", isc.sixten)
150 | + maybe_html_table("Solidity", isc.solidity)
151 | + maybe_html_table("SQL", isc.sql)
152 | + maybe_html_table("Squirrel", isc.squirrel)
153 | + maybe_html_table("Standard ML", isc.sml)
154 | + maybe_html_table("Swift", isc.swift)
155 | + maybe_html_table("TCL", isc.tcl)
156 | + maybe_html_table("Terraform", isc.terraform)
157 | + maybe_html_table("TeX", isc.tex)
158 | + maybe_html_table("Thrift", isc.thrift)
159 | + maybe_html_table("TLA+", isc.tla)
160 | + maybe_html_table("TOML", isc.toml)
161 | + maybe_html_table("TypeScript", isc.typescript)
162 | + maybe_html_table("Vala", isc.vala)
163 | + maybe_html_table("Vagrantfile", isc.vagrantfile)
164 | + maybe_html_table("Verilog", isc.verilog)
165 | + maybe_html_table("VHDL", isc.vhdl)
166 | + maybe_html_table("Vimscript", isc.vimscript)
167 | + maybe_html_table("Visual Basic", isc.vb)
168 | + maybe_html_table("Volt", isc.volt)
169 | + maybe_html_table("Yacc", isc.yacc)
170 | + maybe_html_table("YAML", isc.yaml)
171 | + maybe_html_table("XML", isc.xml)
172 | + maybe_html_table("Zig", isc.zig)
173 | + maybe_html_table("Zimpl", isc.zimpl)
174 | var table_footer = "
"
175 | in
176 | table_header + content + table_footer
177 | end
178 |
179 | fn make_html(isc : source_contents) : string =
180 | let
181 | var header = ""
182 | var footer = ""
183 | in
184 | header + make_table_columns(isc) + footer
185 | end
186 |
187 | fn write_report(isc : source_contents, path : string) : void =
188 | let
189 | val ref = fileref_open_opt(path, file_mode_w)
190 | val () = case+ ref of
191 | | ~Some_vt (x) => let
192 | val to_write = make_html(isc)
193 | val () = fputs0_exn(to_write, x)
194 | val () = fileref_close(x)
195 | in end
196 | | ~None_vt() => bad_file(path)
197 | in end
198 |
--------------------------------------------------------------------------------
/test/data/verilog.v:
--------------------------------------------------------------------------------
1 | //======================================================================
2 | //
3 | // sha256.v
4 | // --------
5 | // Top level wrapper for the SHA-256 hash function providing
6 | // a simple memory like interface with 32 bit data access.
7 | //
8 | //
9 | // Author: Joachim Strombergson
10 | // Copyright (c) 2013, 201, Secworks Sweden AB
11 | // All rights reserved.
12 | //
13 | // Redistribution and use in source and binary forms, with or
14 | // without modification, are permitted provided that the following
15 | // conditions are met:
16 | //
17 | // 1. Redistributions of source code must retain the above copyright
18 | // notice, this list of conditions and the following disclaimer.
19 | //
20 | // 2. Redistributions in binary form must reproduce the above copyright
21 | // notice, this list of conditions and the following disclaimer in
22 | // the documentation and/or other materials provided with the
23 | // distribution.
24 | //
25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 | //
38 | //======================================================================
39 |
40 | module sha256(
41 | // Clock and reset.
42 | input wire clk,
43 | input wire reset_n,
44 |
45 | // Control.
46 | input wire cs,
47 | input wire we,
48 |
49 | // Data ports.
50 | input wire [7 : 0] address,
51 | input wire [31 : 0] write_data,
52 | output wire [31 : 0] read_data,
53 | output wire error
54 | );
55 |
56 | //----------------------------------------------------------------
57 | // Internal constant and parameter definitions.
58 | //----------------------------------------------------------------
59 | localparam ADDR_NAME0 = 8'h00;
60 | localparam ADDR_NAME1 = 8'h01;
61 | localparam ADDR_VERSION = 8'h02;
62 |
63 | localparam ADDR_CTRL = 8'h08;
64 | localparam CTRL_INIT_BIT = 0;
65 | localparam CTRL_NEXT_BIT = 1;
66 | localparam CTRL_MODE_BIT = 2;
67 |
68 | localparam ADDR_STATUS = 8'h09;
69 | localparam STATUS_READY_BIT = 0;
70 | localparam STATUS_VALID_BIT = 1;
71 |
72 | localparam ADDR_BLOCK0 = 8'h10;
73 | localparam ADDR_BLOCK15 = 8'h1f;
74 |
75 | localparam ADDR_DIGEST0 = 8'h20;
76 | localparam ADDR_DIGEST7 = 8'h27;
77 |
78 | localparam CORE_NAME0 = 32'h73686132; // "sha2"
79 | localparam CORE_NAME1 = 32'h2d323536; // "-256"
80 | localparam CORE_VERSION = 32'h312e3830; // "1.80"
81 |
82 | localparam MODE_SHA_224 = 1'h0;
83 | localparam MODE_SHA_256 = 1'h1;
84 |
85 |
86 | //----------------------------------------------------------------
87 | // Registers including update variables and write enable.
88 | //----------------------------------------------------------------
89 | reg init_reg;
90 | reg init_new;
91 |
92 | reg next_reg;
93 | reg next_new;
94 |
95 | reg mode_reg;
96 | reg mode_new;
97 | reg mode_we;
98 |
99 | reg ready_reg;
100 |
101 | reg [31 : 0] block_reg [0 : 15];
102 | reg block_we;
103 |
104 | reg [255 : 0] digest_reg;
105 |
106 | reg digest_valid_reg;
107 |
108 |
109 | //----------------------------------------------------------------
110 | // Wires.
111 | //----------------------------------------------------------------
112 | wire core_ready;
113 | wire [511 : 0] core_block;
114 | wire [255 : 0] core_digest;
115 | wire core_digest_valid;
116 |
117 | reg [31 : 0] tmp_read_data;
118 | reg tmp_error;
119 |
120 |
121 | //----------------------------------------------------------------
122 | // Concurrent connectivity for ports etc.
123 | //----------------------------------------------------------------
124 | assign core_block = {block_reg[00], block_reg[01], block_reg[02], block_reg[03],
125 | block_reg[04], block_reg[05], block_reg[06], block_reg[07],
126 | block_reg[08], block_reg[09], block_reg[10], block_reg[11],
127 | block_reg[12], block_reg[13], block_reg[14], block_reg[15]};
128 |
129 | assign read_data = tmp_read_data;
130 | assign error = tmp_error;
131 |
132 |
133 | //----------------------------------------------------------------
134 | // core instantiation.
135 | //----------------------------------------------------------------
136 | sha256_core core(
137 | .clk(clk),
138 | .reset_n(reset_n),
139 |
140 | .init(init_reg),
141 | .next(next_reg),
142 | .mode(mode_reg),
143 |
144 | .block(core_block),
145 |
146 | .ready(core_ready),
147 |
148 | .digest(core_digest),
149 | .digest_valid(core_digest_valid)
150 | );
151 |
152 |
153 | //----------------------------------------------------------------
154 | // reg_update
155 | //
156 | // Update functionality for all registers in the core.
157 | // All registers are positive edge triggered with asynchronous
158 | // active low reset. All registers have write enable.
159 | //----------------------------------------------------------------
160 | always @ (posedge clk or negedge reset_n)
161 | begin : reg_update
162 | integer i;
163 |
164 | if (!reset_n)
165 | begin
166 | init_reg <= 0;
167 | next_reg <= 0;
168 | ready_reg <= 0;
169 | mode_reg <= MODE_SHA_256;
170 | digest_reg <= 256'h0;
171 | digest_valid_reg <= 0;
172 |
173 | for (i = 0 ; i < 16 ; i = i + 1)
174 | block_reg[i] <= 32'h0;
175 | end
176 | else
177 | begin
178 | ready_reg <= core_ready;
179 | digest_valid_reg <= core_digest_valid;
180 | init_reg <= init_new;
181 | next_reg <= next_new;
182 |
183 | if (mode_we)
184 | mode_reg <= mode_new;
185 |
186 | if (core_digest_valid)
187 | digest_reg <= core_digest;
188 |
189 | if (block_we)
190 | block_reg[address[3 : 0]] <= write_data;
191 | end
192 | end // reg_update
193 |
194 |
195 | //----------------------------------------------------------------
196 | // api_logic
197 | //
198 | // Implementation of the api logic. If cs is enabled will either
199 | // try to write to or read from the internal registers.
200 | //----------------------------------------------------------------
201 | always @*
202 | begin : api_logic
203 | init_new = 0;
204 | next_new = 0;
205 | mode_new = 0;
206 | mode_we = 0;
207 | block_we = 0;
208 | tmp_read_data = 32'h0;
209 | tmp_error = 0;
210 |
211 | if (cs)
212 | begin
213 | if (we)
214 | begin
215 | if (address == ADDR_CTRL)
216 | begin
217 | init_new = write_data[CTRL_INIT_BIT];
218 | next_new = write_data[CTRL_NEXT_BIT];
219 | mode_new = write_data[CTRL_MODE_BIT];
220 | mode_we = 1;
221 | end
222 |
223 | if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
224 | block_we = 1;
225 | end // if (we)
226 |
227 | else
228 | begin
229 | if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
230 | tmp_read_data = block_reg[address[3 : 0]];
231 |
232 | if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7))
233 | tmp_read_data = digest_reg[(7 - (address - ADDR_DIGEST0)) * 32 +: 32];
234 |
235 | case (address)
236 | // Read operations.
237 | ADDR_NAME0:
238 | tmp_read_data = CORE_NAME0;
239 |
240 | ADDR_NAME1:
241 | tmp_read_data = CORE_NAME1;
242 |
243 | ADDR_VERSION:
244 | tmp_read_data = CORE_VERSION;
245 |
246 | ADDR_CTRL:
247 | tmp_read_data = {29'h0, mode_reg, next_reg, init_reg};
248 |
249 | ADDR_STATUS:
250 | tmp_read_data = {30'h0, digest_valid_reg, ready_reg};
251 |
252 | default:
253 | begin
254 | end
255 | endcase // case (address)
256 | end
257 | end
258 | end // addr_decoder
259 | endmodule // sha256
260 |
261 | //======================================================================
262 | // EOF sha256.v
263 | //======================================================================
264 |
--------------------------------------------------------------------------------
/src/polyglot.dats:
--------------------------------------------------------------------------------
1 | %{^
2 | #include
3 | #ifdef ATS_MEMALLOC_GCBDW
4 | #undef GC_H
5 | #define GC_THREADS
6 | #include
7 | #endif
8 |
9 | #include "CATS/nproc.cats"
10 | #include "pthread_mac.h"
11 | %}
12 |
13 | #include "share/atspre_staload.hats"
14 | #include "share/HATS/atslib_staload_libats_libc.hats"
15 | #include "DATS/shared.dats"
16 | #include "$PATSHOMELOCS/ats-concurrency-0.4.8/mylibies.hats"
17 | #include "$PATSHOMELOCS/edit-distance-0.5.0/DATS/edit-distance.dats"
18 | #include "DATS/utils.dats"
19 | #include "DATS/error.dats"
20 | #include "DATS/html.dats"
21 |
22 | staload ML = "libats/ML/SATS/list0.sats"
23 | staload "libats/SATS/deqarray.sats"
24 | staload "libats/SATS/athread.sats"
25 | staload _ = "libats/DATS/deqarray.dats"
26 | staload _ = "libats/DATS/athread.dats"
27 | staload "SATS/nproc.sats"
28 |
29 | val ncpu = get_nprocs{4}()
30 |
31 | fn step_list(s : string, excludes : List0(string)) : List0(string) =
32 | let
33 | var files = streamize_dirname_fname(s)
34 | var ffiles = stream_vt_filter_cloptr(files, lam x => not(bad_dir(x, excludes) && test_file_isdir(s + "/" + x) > 0))
35 |
36 | fun stream2list(x : stream_vt(string)) : List0(string) =
37 | case+ !x of
38 | | ~stream_vt_cons (x, xs) => list_cons(s + "/" + x, stream2list(xs))
39 | | ~stream_vt_nil() => list_nil
40 | in
41 | stream2list(ffiles)
42 | end
43 |
44 | fn step_list_files(s : string, excludes : List0(string)) : List0(string) =
45 | let
46 | var files = streamize_dirname_fname(s)
47 | var ffiles = stream_vt_filter_cloptr(files, lam x => not(bad_dir(x, excludes)) && test_file_isdir(s + "/" + x) = 0)
48 |
49 | fun stream2list(x : stream_vt(string)) : List0(string) =
50 | case+ !x of
51 | | ~stream_vt_cons (x, xs) when s = "." => list_cons(x, stream2list(xs))
52 | | ~stream_vt_cons (x, xs) => list_cons(s + "/" + x, stream2list(xs))
53 | | ~stream_vt_nil() => list_nil
54 | in
55 | stream2list(ffiles)
56 | end
57 |
58 | fn map_depth(xs : List0(string), excludes : List0(string)) : List0(string) =
59 | let
60 | fun loop {i:nat} .. (i : int(i), xs : List0(string), excludes : List0(string)) : List0(string) =
61 | let
62 | var xs0 = list0_filter(g0ofg1(xs), lam x => test_file_isdir(x) > 0)
63 | in
64 | case+ i of
65 | | 0 => g1ofg0(list0_mapjoin(xs0, lam x => if not(bad_dir(x, excludes)) then
66 | g0ofg1(step_list(x, excludes))
67 | else
68 | list0_nil))
69 | | _ =>> g1ofg0(list0_mapjoin(xs0, lam x => if not(bad_dir(x, excludes)) then
70 | let
71 | var ys = step_list(x, excludes)
72 | var zs = step_list_files(x, excludes)
73 | in
74 | g0ofg1(loop(i - 1, ys, excludes)) + g0ofg1(zs)
75 | end
76 | else
77 | if x = "." && i = 3 then
78 | let
79 | var ys = step_list(x, excludes)
80 | var zs = step_list_files(x, excludes)
81 | in
82 | g0ofg1(loop(i - 1, ys, excludes)) + g0ofg1(zs)
83 | end
84 | else
85 | list0_nil))
86 | end
87 | in
88 | loop(3, xs, excludes)
89 | end
90 |
91 | // FIXME this is slow because of the List0
92 | // Also this approach is just silly in general
93 | fn apportion(includes : List0(string), excludes : List0(string)) : List0(List0(string)) =
94 | let
95 | var ys = list0_filter(g0ofg1(includes), lam x => test_file_isdir(x) != 1)
96 | var deep = map_depth(includes, excludes) + g1ofg0(ys)
97 | val n = length(deep) / ncpu
98 |
99 | fun loop { i : nat | i > 0 } .. (i : int(i), acc : List0(string)) : List0(List0(string)) =
100 | if n > 0 then
101 | if n < length(acc) then
102 | let
103 | extern
104 | castfn cast_list(List0(List0(string))) :<> List0(List0(string))
105 |
106 | val (p, q) = list_split_at(acc, n)
107 | var res = if i > 2 then
108 | loop(i - 1, q)
109 | else
110 | q :: nil
111 | in
112 | list_vt2t(p) :: cast_list(res)
113 | end
114 | else
115 | acc :: nil
116 | else
117 | let
118 | // if I replace this with j != 1 it segfaults
119 | fun fill_nil { j : nat | j > 0 } .. (j : int(j)) :<> List0(List0(string)) =
120 | if j > 1 then
121 | nil :: fill_nil(j - 1)
122 | else
123 | nil
124 | in
125 | acc :: fill_nil(ncpu)
126 | end
127 | in
128 | loop(ncpu, deep)
129 | end
130 |
131 | fn handle_unref(x : channel(string)) : void =
132 | case+ channel_unref(x) of
133 | | ~None_vt() => ()
134 | | ~Some_vt (q) => queue_free(q)
135 |
136 | fn work(excludes : List0(string), send : channel(List0(string)), chan : channel(source_contents), verbose : bool) :
137 | void =
138 | {
139 | var n = channel_remove(send)
140 | var x = empty_contents()
141 | val () = map_stream(x, n, excludes, verbose)
142 | val () = channel_insert(chan, x)
143 | val () = handle_unref(chan)
144 | val () = handle_unref(send)
145 | }
146 |
147 | // ideally we want one "large" channel that will handle back-and-forth communication between threads.
148 | fn threads(includes : List0(string), excludes : List0(string), verbose : bool) : source_contents =
149 | let
150 | // this will hold the results sent back
151 | val chan = channel_make(ncpu)
152 | var new_includes = if length(includes) > 0 then
153 | includes
154 | else
155 | list_cons(".", list_nil())
156 | val portions = apportion(new_includes, excludes)
157 |
158 | fun loop { i : nat | i > 0 } .. (i : int(i), chan : !channel(source_contents)) : void =
159 | {
160 | val chan_ = channel_ref(chan)
161 |
162 | // this will simply communicate the work to be done
163 | val send = channel_make(1)
164 | val send_r = channel_ref(send)
165 |
166 | fn maybe_insert {m:nat}(xs : List0(List0(string)), n : int(m), send : !channel(List0(string))) : void =
167 | case+ list_get_at_opt(xs, n) of
168 | | ~Some_vt (x) => channel_insert(send, x)
169 | | ~None_vt() => ()
170 |
171 | val () = maybe_insert(portions, i - 1, send)
172 |
173 | // If we use something lower-level we might get finer control of when things exit?
174 | // Thread pool might be faster (?)
175 | val _ = athread_create_cloptr_exn(llam () =>
176 | work(excludes, send_r, chan_, verbose))
177 | val () = handle_unref(send)
178 | val () = if i >= 2 then
179 | loop(i - 1, chan)
180 | }
181 |
182 | val () = loop(ncpu, chan)
183 |
184 | fun loop_return { i : nat | i >= 0 } .. (i : int(i), chan : !channel(source_contents)) : source_contents =
185 | case+ i of
186 | | 0 => empty_contents()
187 | | _ =>> let
188 | var n = channel_remove(chan)
189 | var m = loop_return(i - 1, chan)
190 | in
191 | m + n
192 | end
193 |
194 | var r = loop_return(ncpu, chan)
195 | val () = ignoret(usleep(90u))
196 | val () = while(channel_refcount(chan) > 1)()
197 | val () = handle_unref(chan)
198 | in
199 | r
200 | end
201 |
202 | implement main0 (argc, argv) =
203 | let
204 | val cli = @{ version = false
205 | , help = false
206 | , no_table = false
207 | , html = false
208 | , no_style = false
209 | , no_parallel = false
210 | , no_colorize = false
211 | , skip_links = false
212 | , verbose = false
213 | , excludes = list_nil()
214 | , includes = list_nil()
215 | } : command_line
216 | val parsed = get_cli(argc, argv, 0, false, cli)
217 | val () = check_cli(parsed)
218 | in
219 | if parsed.help then
220 | (help() ; exit(0))
221 | else
222 | if parsed.version then
223 | (version() ; exit(0))
224 | else
225 | let
226 | var result = if not(parsed.no_parallel) then
227 | threads(parsed.includes, parsed.excludes, parsed.verbose)
228 | else
229 | if length(parsed.includes) > 0 then
230 | let
231 | var x = empty_contents()
232 | val () = map_stream(x, parsed.includes, parsed.excludes, parsed.verbose)
233 | in
234 | x
235 | end
236 | else
237 | let
238 | var x = empty_contents()
239 | val () = map_stream(x, list_cons(".", list_nil()), parsed.excludes, parsed.verbose)
240 | in
241 | x
242 | end
243 | in
244 | if parsed.no_table then
245 | print(make_output(result, not(parsed.no_colorize)))
246 | else
247 | if parsed.html && not(parsed.no_style) then
248 | print(make_html(result))
249 | else
250 | if parsed.html then
251 | print(make_table_columns(result))
252 | else
253 | print(make_table(result, not(parsed.no_colorize)))
254 | end
255 | end
256 |
--------------------------------------------------------------------------------
/SATS/filetype.sats:
--------------------------------------------------------------------------------
1 | // Type for a collection of files (monoidal)
2 | vtypedef file = @{ lines = int, blanks = int, comments = int, files = int }
3 |
4 | // Program state, tracking *all* supported file types in an unboxed structure.
5 | vtypedef source_contents = @{ rust = file
6 | , haskell = file
7 | , ats = file
8 | , python = file
9 | , vimscript = file
10 | , elm = file
11 | , idris = file
12 | , madlang = file
13 | , tex = file
14 | , markdown = file
15 | , yaml = file
16 | , toml = file
17 | , cabal = file
18 | , happy = file
19 | , alex = file
20 | , go = file
21 | , html = file
22 | , css = file
23 | , scss = file
24 | , verilog = file
25 | , vhdl = file
26 | , c = file
27 | , purescript = file
28 | , futhark = file
29 | , brainfuck = file
30 | , ruby = file
31 | , julia = file
32 | , perl = file
33 | , ocaml = file
34 | , agda = file
35 | , cobol = file
36 | , tcl = file
37 | , r = file
38 | , lua = file
39 | , cpp = file
40 | , lalrpop = file
41 | , header = file
42 | , sixten = file
43 | , dhall = file
44 | , ipkg = file
45 | , makefile = file
46 | , justfile = file
47 | , ion = file
48 | , bash = file
49 | , dash = file
50 | , hamlet = file
51 | , cassius = file
52 | , lucius = file
53 | , julius = file
54 | , mercury = file
55 | , yacc = file
56 | , lex = file
57 | , coq = file
58 | , jupyter = file
59 | , java = file
60 | , scala = file
61 | , erlang = file
62 | , elixir = file
63 | , pony = file
64 | , clojure = file
65 | , cabal_project = file
66 | , assembly = file
67 | , nix = file
68 | , php = file
69 | , javascript = file
70 | , kotlin = file
71 | , fsharp = file
72 | , fortran = file
73 | , swift = file
74 | , csharp = file
75 | , nim = file
76 | , cpp_header = file
77 | , elisp = file
78 | , plaintext = file
79 | , rakefile = file
80 | , llvm = file
81 | , autoconf = file
82 | , batch = file
83 | , powershell = file
84 | , m4 = file
85 | , objective_c = file
86 | , automake = file
87 | , carp = file
88 | , shen = file
89 | , greencard = file
90 | , cmm = file
91 | , fluid = file
92 | , plutus = file
93 | , j = file
94 | , blodwen = file
95 | , crystal = file
96 | , racket = file
97 | , ada = file
98 | , sml = file
99 | , isabelle = file
100 | , fstar = file
101 | , d = file
102 | , factor = file
103 | , scheme = file
104 | , chapel = file
105 | , pascal = file
106 | , ragel = file
107 | , xml = file
108 | , awk = file
109 | , sed = file
110 | , k = file
111 | , typescript = file
112 | , coffeescript = file
113 | , red = file
114 | , fish = file
115 | , vb = file
116 | , frege = file
117 | , dart = file
118 | , solidity = file
119 | , egison = file
120 | , zig = file
121 | , sql = file
122 | , felix = file
123 | , qsharp = file
124 | , oz = file
125 | , jai = file
126 | , zimpl = file
127 | , volt = file
128 | , cogent = file
129 | , clean = file
130 | , thrift = file
131 | , vala = file
132 | , apex = file
133 | , sas = file
134 | , nu = file
135 | , haxe = file
136 | , eiffel = file
137 | , tla = file
138 | , lean = file
139 | , io = file
140 | , squirrel = file
141 | , agdalib = file
142 | , cedille = file
143 | , raml = file
144 | , scribble = file
145 | , bibtex = file
146 | , csv = file
147 | , terraform = file
148 | , org = file
149 | , vagrantfile = file
150 | , glsl = file
151 | , dickinson = file
152 | , mirth = file
153 | , flix = file
154 | , jac = file
155 | , gdb = file
156 | , bqn = file
157 | }
158 |
159 | // Sum type representing all supported data types.
160 | datavtype pl_type =
161 | | unknown
162 | | rust of file
163 | | haskell of file
164 | | perl of file
165 | | verilog of file
166 | | vhdl of file
167 | | agda of file
168 | | futhark of file
169 | | ats of file
170 | | idris of file
171 | | python of file
172 | | elm of file
173 | | purescript of file
174 | | vimscript of file
175 | | ocaml of file
176 | | madlang of file
177 | | tex of file
178 | | markdown of file
179 | | yaml of file
180 | | toml of file
181 | | cabal of file
182 | | happy of file
183 | | alex of file
184 | | go of file
185 | | html of file
186 | | css of file
187 | | scss of file
188 | | c of file
189 | | brainfuck of file
190 | | ruby of file
191 | | julia of file
192 | | cobol of file
193 | | tcl of file
194 | | r of file
195 | | lua of file
196 | | cpp of file
197 | | lalrpop of file
198 | | header of file
199 | | sixten of file
200 | | dhall of file
201 | | ipkg of file
202 | | makefile of file
203 | | justfile of file
204 | | ion of file
205 | | bash of file
206 | | dash of file
207 | | hamlet of file
208 | | cassius of file
209 | | lucius of file
210 | | julius of file
211 | | mercury of file
212 | | yacc of file
213 | | lex of file
214 | | coq of file
215 | | jupyter of file
216 | | java of file
217 | | scala of file
218 | | erlang of file
219 | | elixir of file
220 | | pony of file
221 | | clojure of file
222 | | cabal_project of file
223 | | assembly of file
224 | | nix of file
225 | | php of file
226 | | javascript of file
227 | | kotlin of file
228 | | fsharp of file
229 | | fortran of file
230 | | swift of file
231 | | csharp of file
232 | | nim of file
233 | | cpp_header of file
234 | | elisp of file
235 | | rakefile of file
236 | | plaintext of file
237 | | llvm of file
238 | | autoconf of file
239 | | batch of file
240 | | powershell of file
241 | | m4 of file
242 | | objective_c of file
243 | | automake of file
244 | | carp of file
245 | | shen of file
246 | | greencard of file
247 | | cmm of file
248 | | fluid of file
249 | | plutus of file
250 | | j of file
251 | | blodwen of file
252 | | crystal of file
253 | | racket of file
254 | | ada of file
255 | | sml of file
256 | | isabelle of file
257 | | fstar of file
258 | | d of file
259 | | factor of file
260 | | scheme of file
261 | | chapel of file
262 | | pascal of file
263 | | ragel of file
264 | | xml of file
265 | | awk of file
266 | | sed of file
267 | | k of file
268 | | typescript of file
269 | | coffeescript of file
270 | | red of file
271 | | fish of file
272 | | vb of file
273 | | frege of file
274 | | dart of file
275 | | solidity of file
276 | | egison of file
277 | | zig of file
278 | | sql of file
279 | | felix of file
280 | | qsharp of file
281 | | oz of file
282 | | jai of file
283 | | zimpl of file
284 | | volt of file
285 | | cogent of file
286 | | clean of file
287 | | thrift of file
288 | | vala of file
289 | | apex of file
290 | | sas of file
291 | | nu of file
292 | | haxe of file
293 | | eiffel of file
294 | | tla of file
295 | | lean of file
296 | | io of file
297 | | squirrel of file
298 | | agdalib of file
299 | | cedille of file
300 | | raml of file
301 | | scribble of file
302 | | bibtex of file
303 | | csv of file
304 | | terraform of file
305 | | org of file
306 | | vagrantfile of file
307 | | glsl of file
308 | | dickinson of file
309 | | mirth of file
310 | | flix of file
311 | | jac of file
312 | | gdb of file
313 | | bqn of file
314 |
--------------------------------------------------------------------------------
/LANGUAGES.md:
--------------------------------------------------------------------------------
1 | ### Language Support
2 | - [x] Rust
3 | - [x] Haskell
4 | - [x] ATS
5 | - [x] Python
6 | - [x] Vimscript
7 | - [x] Elm
8 | - [x] Idris
9 | - [x] Madlang
10 | - [x] TeX
11 | - [x] Markdown
12 | - [x] YAML
13 | - [x] TOML
14 | - [x] Cabal
15 | - [x] Happy
16 | - [x] Alex
17 | - [x] Go
18 | - [x] HTML
19 | - [x] CSS
20 | - [x] Verilog
21 | - [x] VHDL
22 | - [x] C
23 | - [x] PureScript
24 | - [x] Futhark
25 | - [x] Brainfuck
26 | - [x] Ruby
27 | - [x] Julia
28 | - [x] Perl
29 | - [x] OCaml
30 | - [x] Agda
31 | - [x] COBOL
32 | - [x] TCL
33 | - [x] R
34 | - [x] Lua
35 | - [x] C++
36 | - [x] LALRPOP
37 | - [x] C header
38 | - [x] Sixten
39 | - [x] Dhall
40 | - [x] iPKG
41 | - [x] Makefile
42 | - [x] Justfile
43 | - [x] Ion
44 | - [x] Bash
45 | - [x] Dash
46 | - [x] Hamlet
47 | - [x] Cassius
48 | - [x] Lucius
49 | - [x] Julius
50 | - [x] Mercury
51 | - [x] Yacc
52 | - [x] Lex
53 | - [x] Coq
54 | - [x] Jupyter
55 | - [x] Java
56 | - [x] Scala
57 | - [x] Erlang
58 | [x] Elixir
59 | - [x] Pony
60 | - [x] Clojure
61 | - [x] Cabal project
62 | - [x] Assembly
63 | - [x] Nix
64 | - [x] PHP
65 | - [x] JavaScript
66 | - [x] Kotlin
67 | - [x] F#
68 | - [x] FORTRAN
69 | - [x] Swift
70 | - [x] C#
71 | - [x] Nim
72 | - [x] C++ header
73 | - [x] Emacs Lisp
74 | - [x] Plaintext
75 | - [x] Rakefile
76 | - [x] LLVM
77 | - [x] Autoconf
78 | - [x] Batch
79 | - [x] Powershell
80 | - [x] M4
81 | - [x] Objective C
82 | - [x] Automake
83 | - [x] Margaret
84 | - [x] Carp
85 | - [x] Shen
86 | - [x] Greencard
87 | - [x] C--
88 | - [x] FLTK Data
89 | - [x] Plutus
90 | - [x] J (https://code.jsoftware.com/wiki/Guides/Syntax_Coloring#Vim for
91 | extensions...)
92 | - [x] Blodwen
93 | - [x] Crystal
94 | - [x] Racket
95 | - [x] Ada
96 | - [x] Standard ML
97 | - [x] F\* (`.fst`)
98 | - [x] Isabelle (`.thy`)
99 | - [x] D (`.d`)
100 | - [x] Factor
101 | - [x] Scheme (`.ss`, `.scm`)
102 | - [x] Chapel (`.chpl`)
103 | - [x] awk
104 | - [x] Ragel (`.rl`)
105 | - [x] `.sed` files
106 | - [x] K
107 | - [x] Pascal
108 | - [x] TypeScript
109 | - [x] CoffeeScript (`.coffee`)
110 | - [x] RED
111 | - [x] fish
112 | - [x] visual basic
113 | - [x] Frege (`.fr`)
114 | - [x] Dart
115 | - [x] Solidity (`.sol`)
116 | - [x] Egison (`.egi`)
117 | - [x] Zig
118 | - [x] SQL
119 | - [x] XML
120 | - [x] Felix
121 | - [x] Q#
122 | - [x] Oz
123 | - [x] Jai
124 | - [x] Zimpl
125 | - [x] Volt
126 | - [x] Cogent
127 | - [x] Clean
128 | - [x] Thrift
129 | - [x] Vala
130 | - [x] Apex
131 | - [x] SAS
132 | - [x] Nu
133 | - [x] Haxe
134 | - [x] Eiffel
135 | - [x] TLA+
136 | - [x] Lean
137 | - [x] Io (`.io`, `#`)
138 | - [x] Squirrel (`.nut`, `//`)
139 | - [x] Agda library
140 | - [x] https://cedille.github.io/
141 | - [x] terraform (`.tf`?)
142 | - [x] SCSS
143 | - [x] Vagrantfile
144 | - [x] GLSL
145 | - [x] https://flix.dev/
146 | - [x] jacinda
147 | - [x] gdb
148 | - [x] bqn
149 | - [ ] harlan (`.kfc`, `#`)
150 | - [ ] https://amulet.works/
151 | - [ ] `.yrl` -> Yecc source code (Erlang)
152 | - [ ] Self (`.self`)
153 | - [ ] Linker script
154 | - [ ] Grain (`.gr`, `#`)
155 | - [ ] Boo https://github.com/boo-lang/boo
156 | - [ ] `dappfile`
157 | - [ ] https://github.com/trending/zephir
158 | - [ ] ShaderLab (`.shader`)
159 | - [ ] HLSL (`.cginc`)
160 | - [ ] Literate Haskell
161 | - [ ] Literate happy?
162 | - [ ] Literate Idris
163 | - [ ] DDoc
164 | - [ ] Dockerfile
165 | - [ ] LilyPond (`.ly`)
166 | - [ ] Jenkinsfile (groovy?)
167 | - [ ] mustache
168 | - [ ] jinja
169 | - [ ] groovy
170 | - [ ] Intel hex (`.ihex`)
171 | - [ ] occam
172 | - [ ] Prolog
173 | - [ ] modula
174 | - [ ] LSL http://xahsl.org/sl/ls.html
175 | - [ ] Spire https://github.com/spire/spire
176 | - [ ] dyon
177 | - [ ] ketos
178 | - [ ] puppet (`.pp`)
179 | - [ ] forth (`.fs`, collides with F# (note vim syntax lines))
180 | - [ ] Objective C++
181 | - [ ] Bison (`.yy` among others)
182 | - [ ] Flex (`.lex` among others)
183 | - [ ] `.jats` (enriched JSON)
184 | - [ ] Sass
185 | - [ ] gemfile
186 | - [ ] gemspec
187 | - [ ] rdoc
188 | - [ ] Scons
189 | - [ ] Cmake
190 | - [ ] gradle
191 | - [ ] tulip (`.tlp`)
192 | - [ ] kitten (`.ktn`)
193 | - [ ] siren (`.siren`)
194 | - [ ] emily (`.em`)
195 | - [ ] ceylon
196 | - [ ] Korn shell
197 | - [ ] jsx
198 | - [ ] ColdFusion
199 | - [ ] Balsa
200 | - [ ] Teak
201 | - [ ] Dale
202 | - [ ] microsoft module definition
203 | - [ ] XSLT
204 | - [ ] `.rst`
205 | - [ ] QML
206 | - [ ] `.ini`
207 | - [ ] roff/troff/groff
208 | - [ ] Limbo
209 | - [ ] Terra
210 | - [ ] https://github.com/titan-lang/titan
211 | - [ ] logos (also `.x`)
212 | - [ ] PureBasic
213 | - [ ] Pure https://agraef.github.io/pure-lang/
214 | - [ ] MSBuild
215 | - [ ] Ur
216 | - [ ] SRecoder template
217 | - [ ] emacs dev env
218 | - [ ] Xtend
219 | - [ ] less (fancy CSS)
220 | - [ ] HLSL
221 | - [ ] GNU plot (`.plt`)
222 | - [ ] dtrace
223 | - [ ] `pyf` - F2PY signature
224 | - [ ] quack (`.qk`)
225 | - [ ] saltstack
226 | - [ ] plasma
227 | - [ ] Ballerina (`.bal`, `//`)
228 | - [ ] everything here: http://www.rosettacode.org/wiki/Rosetta_Code
229 | - [ ] SISAL
230 | - [ ] G-code (`.mpt`, `.mpf`, `.nc`)
231 | - [ ] ALGOL (see http://okmij.org/ftp/Babel/index.html#RTRAN ?)
232 | - [ ] flow-matic
233 | - [ ] B
234 | - [ ] delphi
235 | - [ ] Gherkin
236 | - [ ] Pyret
237 | - [ ] Stylus
238 | - [ ] haddock interface
239 | - [ ] NAnt script
240 | - [ ] RobotFramework
241 | - [ ] QML
242 | - [ ] xBase
243 | - [ ] Diderot (`.diderot`)
244 | - [ ] Everything supported by `cloc --show-lang`
245 | - [ ] Also `gocloc --show-lang`, `scc --languages`
246 | - [ ] `.clang-format` files??
247 | - [ ] Hy https://github.com/hylang/hy
248 | - [ ] coconut http://coconut-lang.org/
249 | - [ ] Doxyfile
250 | - [ ] See this list: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
251 | - [ ] Also think of a better way to add new languages
252 | - [ ] Brig PL: https://github.com/klevinism/Brig
253 | - [ ] `.sln`: https://github.com/jemalloc/jemalloc/blob/dev/msvc/jemalloc_vc2015.sln
254 | - [ ] This list: https://github.com/BurntSushi/ripgrep/blob/1d09d4d31ba3ac2eb09edf31e8ec46b2b5cec388/ignore/src/types.rs#L99
255 | - [ ] Clafer http://www.clafer.org/
256 | - [ ] Discus https://github.com/discus-lang/ddc/blob/master/test/ddc-regress/source/01-Discus/10-Parser/Test.dsx
257 | - [ ] Gleam https://github.com/lpil/gleam/blob/51ca433d0f10beab4010d3ba389a27755c71282d/examples/PingPong.gleam
258 | - [ ] BNFC: https://github.com/Cubesoup/Crates/blob/master/parser/tracks.bnfc
259 | - [ ] Unison: http://unisonweb.org/
260 | - [ ] Alms: http://users.eecs.northwestern.edu/~jesse/pubs/alms/
261 | - [ ] This list: https://en.wikipedia.org/wiki/List_of_programming_languages
262 | - [ ] Dale: https://github.com/tomhrr/dale
263 | - [ ] Pikelet: https://github.com/pikelet-lang/pikelet
264 | - [ ] Elvish: https://github.com/elves/elvish
265 | - [ ] Kakaoune script
266 | - [ ] Dreammaker (`.dm`)
267 | - [ ] BrightScript
268 | - [ ] Cosmos: https://github.com/mcsoto/cosmos/blob/master/src/string.cosmos
269 | - [ ] https://github.com/juju2143/flufflepuff
270 | - [ ] https://github.com/SRL/SRL-5/blob/master/SRL/core/color.simba
271 | - [ ] Figure out `.dpr` and `.dfm` file extensions
272 | - [ ] This list: https://github.com/Aaronepower/tokei/blob/master/languages.json
273 | - [ ] NSIS
274 | - [ ] GdScript: https://github.com/trending/gdscript
275 | - [ ] See: https://github.com/MakeNowJust/quine
276 | - [ ] List: https://esolangs.org/wiki/Language_list
277 | - [ ] https://github.com/dzaima/Canvas
278 | - [ ] https://github.com/kite-lang/kite
279 | - [ ] Miranda language
280 | - [x] git@github.com:mirth-lang/mirth.git
281 | - [ ] QCL
282 | - [ ] Gofer (?)
283 | - [ ] SNOBOL (`.sbl`)
284 | - [ ] Zimbu (`.zu`)
285 | - [ ] Dao Script https://github.com/daokoder/dao
286 | - [ ] http://hackage.haskell.org/package/dao
287 | - [ ] SparForte: https://github.com/kburtch/SparForte
288 | - [ ] SourcePawn
289 | - [ ] LOLCODE https://github.com/trending/lolcode
290 | - [ ] REBOL (`.r`, `.reb`)
291 | - [ ] Frenetic (https://github.com/frenetic-lang/frenetic)
292 | - [ ] COMIT https://en.wikipedia.org/wiki/COMIT
293 | - [ ] TRAC https://en.wikipedia.org/wiki/TRAC_(programming_language)
294 | - [ ] intercal: http://catb.org/esr/intercal/
295 | - [ ] stax: https://github.com/tomtheisen/stax
296 | - [ ] V: https://github.com/DJMcMayhem/V
297 | - [ ] SOGL: https://github.com/dzaima/SOGL
298 | - [ ] Retina: https://github.com/m-ender/retina
299 | - [ ] 05AB1E: https://github.com/Adriandmen/05AB1E
300 | - [ ] JsTx: https://github.com/Quantum64/Jstx
301 | - [ ] Pyth: https://esolangs.org/wiki/Pyth
302 | - [ ] Jelly: https://github.com/DennisMitchell/jellylanguage
303 | - [ ] https://github.com/somebody1234/Charcoal
304 | - [ ] Nawk
305 | - [ ] Gambit
306 | - [ ] Guile
307 | - [ ] Icon
308 | - [ ] Hoon
309 | - [ ] Mint https://github.com/mint-lang/mint
310 | - [ ] SuperCollider (`.sc`)
311 | - [ ] Stan (`.stan`)
312 | - [ ] Smali (`.smali`; `#`)
313 | - [ ] Rexx (`.rexx`)
314 | - [ ] https://github.com/joakimthun/Elsa
315 | - [ ] https://github.com/pugjs/pug
316 | - [ ] https://github.com/trending/piglatin
317 | - [ ] https://github.com/trending/stata
318 | - [ ] BitBake
319 | - [ ] https://en.wikipedia.org/wiki/Cadence_SKILL
320 | - [ ] https://github.com/ftripier/spookyc
321 | - [ ] https://github.com/redprl/sml-redprl
322 | - [ ] https://github.com/jonsterling/jonprl
323 | - [ ] http://www.nuprl.org/
324 | - [ ] http://www.axiom-developer.org/
325 | - [ ] https://zdnet1.cbsistatic.com/hub/i/r/2018/08/16/ea443352-5708-4c04-aa77-1a5d8b6b8b2d/resize/770xauto/78ef73d9bdb2b77e1aa8dbdfe4afee5f/lang-rank-618-1-1024x708.png
326 | - [ ] http://focalize.inria.fr/
327 | - [ ] https://www.npmjs.com/package/code-counter
328 | - [ ] https://www.amber-lang.net/
329 | - [ ] https://en.wikipedia.org/wiki/JOSS
330 | - [ ] http://shakespearelang.sourceforge.net/report/shakespeare
331 | - [ ] Unreal Script
332 | - [ ] Lobster (`.lobster`, `//`)
333 | - [ ] Nomyx (http://hackage.haskell.org/package/Nomyx-Language)
334 | - [ ] http://feldspar.github.io/
335 | - [ ] https://code.google.com/archive/p/foma/
336 | - [ ] aurochs http://hackage.haskell.org/package/Aurochs-0.1/src/test.aur
337 | - [ ] http://hackage.haskell.org/package/descript-lang
338 | - [ ] http://hackage.haskell.org/package/axel
339 | - [ ] http://hackage.haskell.org/package/atomo
340 | - [ ] http://hackage.haskell.org/package/hwhile
341 | - [ ] https://hacklang.org/
342 | - [ ] Skew http://skew-lang.org/
343 | - [ ] https://extemporelang.github.io/
344 | - [ ] https://myrlang.org/
345 | - [ ] Rum: https://github.com/vrom911/Compiler
346 | - [ ] Icon
347 | - [ ] Joy
348 | - [ ] smalltalk
349 | - [ ] spry https://github.com/gokr/spry
350 | - [ ] Ren
351 | - [ ] Kit https://github.com/kitlang/kit
352 | - [ ] unison https://github.com/unisonweb/unison
353 | - [ ] luna https://github.com/luna/luna
354 | - [ ] Skip (`.sk`, `//`)
355 | - [ ] https://github.com/Microsoft/dafny
356 | - [ ] euclid
357 | - [ ] CLU
358 | - [ ] Ceptre: https://github.com/chrisamaphone/interactive-lp/blob/master/examples/love-triangle.cep
359 | - [ ] granule https://github.com/granule-project/granule
360 | - [ ] https://github.com/pigworker/Syrup
361 | - [ ] https://github.com/lbochenek/eggplant
362 | - [ ] http://www-sop.inria.fr/meije/rp/ROS/Tt-SM.html
363 | - [ ] http://www.minizinc.org/
364 | - [ ] https://alan-platform.com/about/
365 | - [ ] https://github.com/Zolang/Zolang
366 | - [ ] https://github.com/m-ender/retina
367 | - [ ] https://esolangs.org/wiki/Fish
368 | - [ ] https://github.com/fergusq/roda
369 | - [ ] https://github.com/DJMcMayhem/Brain-Flak
370 | - [ ] https://github.com/maiavictor/formality
371 | - [ ] https://www.cs.bu.edu/~hwxi/DML/DML.html
372 | - [ ] http://pvs.csl.sri.com/
373 | - [ ] BlueSpec
374 | - [ ] hap: https://github.com/evincarofautumn/Hap/blob/master/test/and.hap
375 | - [ ] https://github.com/munificent/vigil
376 | - [ ] https://github.com/DennisMitchell/jellylanguage
377 | - [ ] https://bitbucket.org/zacharyjtaylor/my-language
378 | - [ ] Zot (.zot)
379 | - [ ] http://www.earl-grey.io/
380 | - [ ] https://github.com/matijapretnar/eff/
381 | - [ ] Nearley (`.ne`)
382 | - [ ] https://github.com/playXE/Jazz
383 | - [ ] https://github.com/MLstate/opalang
384 | - [ ] https://github.com/grain-lang/grain
385 | - [ ] https://github.com/p-org/P
386 | - [ ] https://adamant-lang.org/
387 | - [ ] https://github.com/flax-lang/flax
388 | - [ ] https://github.com/anoniscoding/yorlang
389 | - [ ] https://en.wikipedia.org/wiki/GNU_Guile
390 | - [ ] https://en.wikipedia.org/wiki/F-Script_(programming_language)
391 | - [ ] https://github.com/p-org/P
392 | - [ ] http://microsoft.github.io/ivy/language.html
393 | - [ ] Id90 programming language
394 | - [ ] `.qs` can also be qtscript?
395 | - [ ] https://github.com/dibyendumajumdar/ravi
396 | - [ ] https://github.com/lhartikk/ArnoldC
397 | - [ ] https://en.wikipedia.org/wiki/SPARK_(programming_language)
398 | - [ ] https://github.com/pikatchu/LinearML
399 | - [ ] https://github.com/tov/alms
400 | - [ ] https://github.com/OpenEuphoria/euphoria
401 | - [ ] https://github.com/wasplang/wasp
402 | - [ ] http://www.ceu-lang.org/
403 | - [ ] https://github.com/lys-lang/lys
404 | - [ ] http://gittup.org/tup/manual.html
405 | - [ ] https://github.com/wren-lang/wren
406 | - [ ] https://github.com/kivikakk/comrak/blob/master/src/lexer.pest
407 | - [ ] https://github.com/nickmqb/muon
408 | - [ ] https://github.com/Microsoft/BosqueLanguage
409 | - [ ] https://github.com/historicalsource/deadline/blob/master/clock.zil
410 | - [ ] https://github.com/ffwff/hana
411 | - [ ] https://sites.google.com/view/lcore
412 | - [ ] https://www.cs.ox.ac.uk/conferences/fscd2017/preproceedings_unprotected/TLLA_Orchard.pdf
413 | - [ ] https://granule-project.github.io/granule.html
414 | - [ ] https://link.springer.com/chapter/10.1007/3-540-45337-7_9
415 | - [ ] Q# and Q (APL dialect)
416 | - [ ] moose (.moo) https://github.com/Mercury-Language/mercury/tree/master/extras/moose
417 | - [ ] https://github.com/elendiastarman/Minkolang
418 | - [ ] http://norstrulde.org/language84/
419 | - [ ] https://mun-lang.org
420 | - [ ] org-mode
421 | - [ ] https://github.com/dundalek/awesome-lisp-languages
422 | - [ ] koka
423 | - [ ] https://github.com/sweirich/trellys
424 | - [ ] https://sage.soe.ucsc.edu/
425 | - [ ] http://whiley.org/about/overview/
426 | - [ ] http://frama-c.com/
427 | - [ ] https://links-lang.org/
428 | - [ ] http://www.scribble.org/
429 | - [ ] http://www.cduce.org/
430 | - [ ] https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/toplasFAST.pdf
431 | - [ ] https://en.wikipedia.org/wiki/Frink_(programming_language)
432 | - [ ] http://manticore.cs.uchicago.edu/
433 | - [ ] https://legion.stanford.edu/overview/index.html
434 | - [ ] https://en.wikipedia.org/wiki/Telescript_(programming_language)
435 | - [ ] https://en.wikipedia.org/wiki/Obliq
436 | - [ ] http://concurnas.com/
437 | - [ ] https://spatial-lang.org
438 | - [ ] https://www.chisel-lang.org/chisel3/
439 | - [ ] https://joypy.osdn.io/
440 | - [ ] https://mortoray.com/2018/08/07/sadly-i-must-say-goodbye-to-leaf-my-programming-language/
441 | - [ ] https://www.cl.cam.ac.uk/~pes20/lem/
442 | - [ ] https://github.com/AlexCouch/beagle-lang
443 | - [ ] ratfor
444 | - [ ] http://www.e-pig.org
445 | - [ ] https://www.microsoft.com/en-us/research/project/spec/?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fprojects%2Fspecsharp%2F
446 | (Spec#, JML, AsmL, ...)
447 | - [ ] https://github.com/TerryCavanagh/VVVVVV/search?l=angelscript lol?
448 | - [ ] https://clio-lang.org/
449 | - [ ] https://github.com/beefytech/Beef/
450 | - [ ] http://blog.oxyllang.org/
451 | - [ ] https://github.com/0x0f0f0f/minicaml
452 | - [ ] https://github.com/skx/monkey
453 | - [ ] all languages in sidebar: https://concatenative.org/wiki/view/Factor/Deployment
454 | - [ ] https://github.com/microsoft/verona
455 | - [ ] https://seq-lang.org
456 | - [ ] https://github.com/paulstansifer/unseemly
457 | - [ ] https://odin-lang.org/
458 | - [ ] https://www.cs.cmu.edu/~scandal/nesl.html
459 | - [ ] ReasonML
460 | - [ ] reason https://github.com/reasonml-community/reason-react-hacker-news/blob/8ba4b7855e7c40cd5f2d575beb9a381c8f8ff7e5/src/NotFound.re
461 | - [ ] https://flix.dev/#/
462 | - [ ] http://discus-lang.org/
463 | - [ ] https://moonscript.org/
464 | - [ ] https://github.com/ryvnf/czc/
465 | - [ ] https://spectrum.ieee.org/tech-talk/computing/software/classical-chinese
466 | - [ ] http://www.grammaticalframework.org/
467 | - [ ] Fennel language
468 | - [ ] https://www.mint-lang.com
469 | - [ ] https://github.com/finkel-lang/finkel
470 | - [ ] https://tuplexlanguage.github.io/tuplex/index.html
471 | - [ ] https://en.wikipedia.org/wiki/CWEB
472 | - [ ] https://github.com/bee-lang/bee
473 | - [ ] https://github.com/julianhyde/morel
474 | - [ ] http://coconut-lang.org/
475 | - [ ] https://github.com/vighneshq/sage-lang
476 | - [ ] http://pyos.github.io/dg/
477 | - [ ] https://github.com/syscolabs/kasaya
478 | - [ ] http://www.timber-lang.org
479 | - [ ] https://ballerina.io
480 | - [ ] https://github.com/sorbet/sorbet/search?l=starlark
481 | - [ ] http://lang5.sourceforge.net/tiki-index.php
482 | - [ ] http://phix.x10.mx/
483 | - [ ] https://github.com/p-org/P
484 | - [ ] https://github.com/rxi/fe
485 | - [ ] http://heavyfishdesign.com/getting_started.html
486 | - [ ] https://github.com/e-wrks/edh
487 | - [ ] https://ptls.dev/docs.html
488 | - [ ] hakaru
489 | - [ ] http://northarc.com/callisto/
490 | - [ ] https://github.com/anssihalmeaho/funl
491 | - [ ] https://dev.to/awwsmm/20-coolest-features-of-non-java-jvm-languages-2p4h
492 | - [ ] https://github.com/vtereshkov/umka-lang
493 | - [ ] https://github.com/u2zv1wx/neut
494 | - [ ] https://github.com/cohaereo/latt
495 | - [ ] https://functional.blog/2020/05/25/designing-a-functional-programming-language-yatta/
496 | - [ ] https://web.archive.org/web/20091207092823/http://www.scs.leeds.ac.uk/hill/GOEDEL/expgoedel.html
497 | [ ] http://pll.cpsc.ucalgary.ca/charity1/www/home.html
498 | - [ ] https://cryptol.net/downloads.html
499 | - [ ] https://github.com/elucent/basil
500 | - [ ] https://manool.org/
501 | - [ ] https://github.com/digama0/mm0
502 | - [ ] https://github.com/ollef/sixty
503 | - [ ] https://janet-lang.org/
504 | - [ ] https://mitten-lang.org/
505 | - [ ] https://github.com/aradi/fypp
506 | - [ ] https://github.com/microsoft/BosqueLanguage
507 | - [ ] https://github.com/Morgan-Stanley/hobbes
508 | - [ ] https://github.com/mun-lang/mun
509 | - [ ] https://concurnas.com/
510 | - [ ] https://github.com/cuelang/cue
511 | - [ ] https://github.com/gelisam/klister/blob/master/stdlib/prelude.kl
512 | - [ ] https://kappalanguage.org/
513 | - [ ] https://github.com/marcobambini/gravity
514 | - [ ] https://wren.io/
515 | - [ ] https://www.hamler-lang.org/
516 | - [ ] https://frinklang.org/
517 | - [ http://www.dip-lang.org/
518 | - [ ] `.cow` (cowfile)
519 | - [ ] https://github.com/Camto/calc/
520 | - [ ] https://github.com/bauripalash/mewmew
521 | - [ ] https://github.com/Storyyeller/cubiml-demo
522 | - [ ] https://www.reddit.com/r/ProgrammingLanguages/comments/hplj2i/vale/
523 | - [ ] https://www.frostlang.org/
524 | - [ ] https://github.com/ELENA-LANG/elena-lang/releases/tag/v5.0.23
525 | - [ ] http://citrine-lang.org/
526 | - [ ] https://github.com/sagebind/riptide
527 | - [ ] https://jinx-lang.org/
528 | - [ ] https://qed-lang.org/
529 | - [ ] https://github.com/RockstarLang/rockstar
530 | - [ ] https://gist.github.com/macintux/6349828#alternative-languages-targeting-the-erlang-vm
531 | - [ ] https://github.com/somebody1234/Charcoal
532 | - [ ] http://norstrulde.org/language84/
533 | - [ ] https://www.emojicode.org/
534 | - [ ] http://www.oilshell.org/cross-ref.html?tag=oil-language#oil-language
535 | - [ ] https://miniscript.org/
536 | - [ ] https://www.modelica.org/
537 | - [ ] https://gitlab.com/umbrellaresearch/yoga2/
538 | - [ ] https://fennel-lang.org/
539 | - [ ] https://github.com/adam-mcdaniel/oakc
540 | - [ ] lua shebang: https://github.com/facebookresearch/CParser/blob/master/lcpp#L1
541 | - [ ] https://elena-lang.github.io/
542 | - [ ] https://stackoverflow.blog/2020/08/24/motoko-the-language-that-turns-the-web-into-a-computer/
543 | - [ ] https://github.com/toymachine/park-lang
544 | - [ ] https://github.com/llaisdy/beam_languages#languages-28
545 | - [ ] http://www.txl.ca/txl-abouttxl.html
546 | - [ ] http://www.kevinalbrecht.com/code/joy-mirror/joy.html
547 | - [ ] http://www.nsl.com/k/f/f.htm
548 | - [ ] https://cryptm.org/xs/installation.html
549 | - [ ] https://manool.org/
550 | - [ ] http://www.nars2000.org/
551 | - [ ] https://github.com/vtereshkov/umka-lang
552 | - [ ] http://www.om-language.org/
553 | - [ ] https://www.reddit.com/r/manool/comments/jo84xr/native_runtime_performance_for_a_highlevel/
554 | - [ ] https://marcobambini.github.io/gravity/#/README
555 | - [ ] https://github.com/WeirdConstructor/WLambda
556 | - [ ] https://github.com/gramlang/gram
557 | - [ ] https://www.play-lang.dev/
558 | - [ ] https://chaos-lang.org/
559 | - [ ] https://github.com/vrtbl/passerine
560 | - [ ] odin language
561 | - [ ] https://keli-language.gitbook.io/doc/
562 | - [ ] https://elv.sh/
563 | - [ ] https://souffle-lang.github.io/
564 | - [ ] https://en.wikipedia.org/wiki/FriCAS
565 | - [ ] https://www.blech-lang.org/
566 | - [ ] https://macoy.me/blog/programming/CakelispIntro
567 | - [ ] https://gamelisp.rs/
568 | - [ ] https://github.com/topshell-language/topshell
569 | - [ ] http://www.juniper-lang.org/
570 | - [ ] https://github.com/MCSH/rumi
571 | - [ ] https://github.com/jcolag/Thue
572 | - [ ] https://github.com/microsoft/BosqueLanguage
573 | - [ ] https://github.com/mrakgr/The-Spiral-Language
574 | - [ ] https://www.reddit.com/r/ProgrammingLanguages/comments/lizzh4/candy/
575 | - [ ] https://github.com/candy-lang/candy
576 | - [ ] https://www.reddit.com/r/ProgrammingLanguages/comments/ljdj30/just_a_language_like_make_except_not_a_build/
577 | - [ ] https://www.reddit.com/r/ProgrammingLanguages/comments/ljkavx/aulang_a_fast_and_simple_scripting_language/
578 | - [ ] https://github.com/jameshaydon/lawvere
579 | - [ ] https://github.com/odddollar/Container-lang
580 | - [ ] https://github.com/nau/lasca-compiler/
581 | - [ ] https://github.com/TaconeoMental/WaidLang
582 | - [ ] http://www.adapplang.com/
583 | - [ ] http://seed7.sourceforge.net/
584 | - [ ] https://intuitiveexplanations.com/tech/kalyn
585 | - [ ] https://github.com/P-bibs/skiff/
586 | - [ ] https://grain-lang.org/
587 | - [ ] https://ballerina.io/
588 | - [ ] https://ren-lang.github.io/
589 | - [ ] http://100r.co/site/orca.html
590 | - [ ] https://blog.toit.io/the-toit-language-is-now-open-source-14bdcb1604d9
591 | - [ ] https://docs.toit.io/language
592 | - [ ] https://ampl.com/
593 | - [ ] https://tablam.org/
594 | - [ ] `.x` (linker script)
595 | - [ ] http://www.timber-lang.org/
596 | - [ ] http://cth.altocumulus.org/~hallgren/Alfa/
597 | - [ ] https://github.com/cognate-lang/cognate
598 | - [ ] https://github.com/erg-lang/erg
599 | - [ ] Mezzo
600 | - [ ] https://ki-lang.dev/
601 | - [ ] https://www.northarc.com/wrench/www/
602 | - [ ] https://antelang.org/
603 | - [ ] https://github.com/Jaysmito101/tovie/
604 | - [ ] https://github.com/WheretIB/nullc
605 | - [ ] https://www.nial-array-language.org
606 | - [ ] https://github.com/coalton-lang/coalton
607 | - [ ] https://github.com/seven1m/natalie
608 | - [ ] https://codelani.com/lists/languages.html
609 | - [ ] https://billwadge.com/2022/01/13/functional-programming-for-the-rest-of-us-get-pyfl-now/
610 | - [ ] https://en.wikipedia.org/wiki/Esterel
611 | - [ ] https://vale.dev
612 | - [ ] https://github.com/justlucdewit/cod
613 | - [ ] https://github.com/austral/austral/
614 | - [ ] https://haml.info/
615 | - [ ] https://github.com/pugjs/pug
616 |
--------------------------------------------------------------------------------
/test/data/Python.y:
--------------------------------------------------------------------------------
1 | {
2 | -----------------------------------------------------------------------------
3 | -- |
4 | -- Module : Language.Python.Version3.Parser.Parser
5 | -- Copyright : (c) 2009 Bernie Pope
6 | -- License : BSD-style
7 | -- Maintainer : bjpop@csse.unimelb.edu.au
8 | -- Stability : experimental
9 | -- Portability : ghc
10 | --
11 | -- Implementation of the Python version 3 parser. Generated by happy.
12 | -----------------------------------------------------------------------------
13 |
14 | module Language.Python.Version3.Parser.Parser (parseFileInput, parseSingleInput, parseEval) where
15 |
16 | import Language.Python.Version3.Parser.Lexer
17 | import Language.Python.Common.Token as Token
18 | import Language.Python.Common.AST as AST
19 | import Language.Python.Common.ParserUtils
20 | import Language.Python.Common.ParserMonad
21 | import Language.Python.Common.SrcLocation
22 | import Data.Either (rights, either)
23 | import Data.Maybe (maybeToList)
24 | }
25 |
26 | %name parseFileInput file_input
27 | %name parseSingleInput single_input
28 | %name parseEval eval_input
29 |
30 | %tokentype { Token }
31 | %error { parseError }
32 | %monad { P } { thenP } { returnP }
33 | %lexer { lexCont } { EOFToken {} }
34 |
35 | %token
36 | '=' { AssignToken {} }
37 | '(' { LeftRoundBracketToken {} }
38 | ')' { RightRoundBracketToken {} }
39 | '[' { LeftSquareBracketToken {} }
40 | ']' { RightSquareBracketToken {} }
41 | '{' { LeftBraceToken {} }
42 | '}' { RightBraceToken {} }
43 | ',' { CommaToken {} }
44 | ';' { SemiColonToken {} }
45 | ':' { ColonToken {} }
46 | '+' { PlusToken {} }
47 | '-' { MinusToken {} }
48 | '*' { MultToken {} }
49 | '**' { ExponentToken {} }
50 | '/' { DivToken {} }
51 | '//' { FloorDivToken {} }
52 | '>' { GreaterThanToken {} }
53 | '<' { LessThanToken {} }
54 | '==' { EqualityToken {} }
55 | '>=' { GreaterThanEqualsToken {} }
56 | '<=' { LessThanEqualsToken {} }
57 | '|' { BinaryOrToken {} }
58 | '^' { XorToken {} }
59 | '&' { BinaryAndToken {} }
60 | '>>' { ShiftRightToken {} }
61 | '<<' { ShiftLeftToken {} }
62 | '%' { ModuloToken {} }
63 | '~' { TildeToken {} }
64 | '!=' { NotEqualsToken {} }
65 | '.' { DotToken {} }
66 | '...' { EllipsisToken {} }
67 | '+=' { PlusAssignToken {} }
68 | '-=' { MinusAssignToken {} }
69 | '*=' { MultAssignToken {} }
70 | '/=' { DivAssignToken {} }
71 | '%=' { ModAssignToken {} }
72 | '**=' { PowAssignToken {} }
73 | '&=' { BinAndAssignToken {} }
74 | '|=' { BinOrAssignToken {} }
75 | '^=' { BinXorAssignToken {} }
76 | '<<=' { LeftShiftAssignToken {} }
77 | '>>=' { RightShiftAssignToken {} }
78 | '//=' { FloorDivAssignToken {} }
79 | '@' { AtToken {} }
80 | '->' { RightArrowToken {} }
81 | 'and' { AndToken {} }
82 | 'as' { AsToken {} }
83 | 'assert' { AssertToken {} }
84 | 'break' { BreakToken {} }
85 | 'bytestring' { ByteStringToken {} }
86 | 'class' { ClassToken {} }
87 | 'continue' { ContinueToken {} }
88 | 'dedent' { DedentToken {} }
89 | 'def' { DefToken {} }
90 | 'del' { DeleteToken {} }
91 | 'elif' { ElifToken {} }
92 | 'else' { ElseToken {} }
93 | 'except' { ExceptToken {} }
94 | 'False' { FalseToken {} }
95 | 'finally' { FinallyToken {} }
96 | 'float' { FloatToken {} }
97 | 'for' { ForToken {} }
98 | 'from' { FromToken {} }
99 | 'global' { GlobalToken {} }
100 | 'ident' { IdentifierToken {} }
101 | 'if' { IfToken {} }
102 | 'imaginary' { ImaginaryToken {} }
103 | 'import' { ImportToken {} }
104 | 'indent' { IndentToken {} }
105 | 'in' { InToken {} }
106 | 'integer' { IntegerToken {} }
107 | 'is' { IsToken {} }
108 | 'lambda' { LambdaToken {} }
109 | 'NEWLINE' { NewlineToken {} }
110 | 'None' { NoneToken {} }
111 | 'nonlocal' { NonLocalToken {} }
112 | 'not' { NotToken {} }
113 | 'or' { OrToken {} }
114 | 'pass' { PassToken {} }
115 | 'raise' { RaiseToken {} }
116 | 'return' { ReturnToken {} }
117 | 'string' { StringToken {} }
118 | 'True' { TrueToken {} }
119 | 'try' { TryToken {} }
120 | 'unicodestring' { UnicodeStringToken {} }
121 | 'while' { WhileToken {} }
122 | 'with' { WithToken {} }
123 | 'yield' { YieldToken {} }
124 |
125 | %%
126 |
127 | pair(p,q): p q { ($1, $2) }
128 |
129 | left(p,q): p q { $1 }
130 | right(p,q): p q { $2 }
131 |
132 | or(p,q)
133 | : p { $1 }
134 | | q { $1 }
135 |
136 | either(p,q)
137 | : p { Left $1 }
138 | | q { Right $1 }
139 |
140 | opt(p)
141 | : { Nothing }
142 | | p { Just $1 }
143 |
144 | rev_list1(p)
145 | : p { [$1] }
146 | | rev_list1(p) p { $2 : $1 }
147 |
148 | many1(p)
149 | : rev_list1(p) { reverse $1 }
150 |
151 | many0(p)
152 | : many1(p) { $1 }
153 | | { [] }
154 |
155 | sepOptEndBy(p,sep)
156 | : sepByRev(p,sep) ',' { reverse $1 }
157 | | sepByRev(p,sep) { reverse $1 }
158 |
159 | sepBy(p,sep): sepByRev(p,sep) { reverse $1 }
160 |
161 | sepByRev(p,sep)
162 | : p { [$1] }
163 | | sepByRev(p,sep) sep p { $3 : $1 }
164 |
165 | NAME :: { IdentSpan }
166 | NAME : 'ident' { Ident (token_literal $1) (getSpan $1) }
167 |
168 | {-
169 | Note: newline tokens in the grammar:
170 | It seems there are some dubious uses of NEWLINE in the grammar.
171 | This is corroborated by this posting:
172 | http://mail.python.org/pipermail/python-dev/2005-October/057014.html
173 | The general idea is that the lexer does not generate NEWLINE tokens for
174 | lines which contain only spaces or comments. However, the grammar sometimes
175 | suggests that such tokens may exist.
176 | -}
177 |
178 | -- single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
179 |
180 | {-
181 | We don't support the newline at the end of a compound stmt
182 | because the lexer would not produce a newline there. It seems like a weirdness
183 | in the way the interactive input works.
184 | -}
185 |
186 | single_input :: { [StatementSpan] }
187 | single_input
188 | : 'NEWLINE' { [] }
189 | | simple_stmt { $1 }
190 | | compound_stmt {- No newline here! -} { [$1] }
191 |
192 | -- file_input: (NEWLINE | stmt)* ENDMARKER
193 |
194 | file_input :: { ModuleSpan }
195 | file_input
196 | : many0(either('NEWLINE',stmt)) {- No need to mention ENDMARKER -}
197 | { Module (concat (rights $1)) }
198 |
199 | -- eval_input: testlist NEWLINE* ENDMARKER
200 |
201 | eval_input :: { ExprSpan }
202 | eval_input : testlist many0('NEWLINE') {- No need to mention ENDMARKER -} { $1 }
203 |
204 | -- decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
205 |
206 | opt_paren_arg_list :: { [ArgumentSpan] }
207 | opt_paren_arg_list: opt(paren_arg_list) { (concat (maybeToList (fmap fst $1))) }
208 |
209 | paren_arg_list :: { ([ArgumentSpan], SrcSpan) }
210 | paren_arg_list : '(' optional_arg_list ')' { ($2, spanning $1 $3) }
211 |
212 | decorator :: { DecoratorSpan }
213 | decorator
214 | : '@' dotted_name opt_paren_arg_list 'NEWLINE'
215 | { makeDecorator $1 $2 $3 }
216 |
217 | -- decorators: decorator+
218 |
219 | decorators :: { [DecoratorSpan] }
220 | decorators : many1(decorator) { $1 }
221 |
222 | -- decorated: decorators (classdef | funcdef)
223 |
224 | decorated :: { StatementSpan }
225 | decorated
226 | : decorators or(classdef,funcdef)
227 | { makeDecorated $1 $2 }
228 |
229 | -- funcdef: 'def' NAME parameters ['->' test] ':' suite
230 |
231 | funcdef :: { StatementSpan }
232 | funcdef
233 | : 'def' NAME parameters opt(right('->',test)) ':' suite
234 | { makeFun $1 $2 $3 $4 $6 }
235 |
236 | -- parameters: '(' [typedargslist] ')'
237 |
238 | parameters :: { [ParameterSpan] }
239 | parameters : '(' opt(typedargslist) ')' { concat (maybeToList $2) }
240 |
241 | {-
242 | typedargslist: ((tfpdef ['=' test] ',')*
243 | ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
244 | | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
245 | -}
246 |
247 | {- Same pattern as argslist and varargslist -}
248 |
249 | typedargslist :: { [ParameterSpan] }
250 | typedargslist: sepOptEndBy(one_typedargs_param,',') {% checkParameters $1 }
251 |
252 | one_typedargs_param :: { ParameterSpan }
253 | one_typedargs_param
254 | : tfpdef optional_default { makeParam $1 $2 }
255 | | '*' opt(tfpdef) { makeStarParam $1 $2 }
256 | | '**' tfpdef { makeStarStarParam $1 $2 }
257 |
258 | optional_default :: { Maybe ExprSpan }
259 | optional_default: opt(equals_test) { $1 }
260 |
261 | equals_test :: { ExprSpan }
262 | equals_test: '=' test { $2 }
263 |
264 | {- tfpdef: NAME [':' test] -}
265 |
266 | tfpdef :: { (IdentSpan, Maybe ExprSpan) }
267 | tfpdef : NAME opt(colon_test) { ($1, $2) }
268 |
269 | colon_test :: { ExprSpan }
270 | colon_test: ':' test { $2 }
271 |
272 | {-
273 | varargslist: ((vfpdef ['=' test] ',')* ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
274 |
275 | -}
276 |
277 | {-
278 | There is some tedious similarity in these rules to the ones for
279 | TypedArgsList. varargslist is used for lambda functions, and they
280 | do not have parentheses around them (unlike function definitions).
281 | Therefore lambda parameters cannot have the optional annotations
282 | that normal functions can, because the annotations are introduced
283 | using a colon. This would cause ambibguity with the colon
284 | that marks the end of the lambda parameter list!
285 | -}
286 |
287 | varargslist :: { [ParameterSpan] }
288 | varargslist : sepOptEndBy(one_varargs_param,',') {% checkParameters $1 }
289 |
290 | one_varargs_param :: { ParameterSpan }
291 | one_varargs_param
292 | : '*' optvfpdef { makeStarParam $1 $2 }
293 | | '**' vfpdef { makeStarStarParam $1 ($2, Nothing) }
294 | | vfpdef optional_default { makeParam ($1, Nothing) $2 }
295 |
296 | -- vfpdef: NAME
297 | vfpdef :: { IdentSpan }
298 | vfpdef : NAME { $1 }
299 |
300 | optvfpdef :: { Maybe (IdentSpan, Maybe ExprSpan) }
301 | optvfpdef
302 | : {- empty -} { Nothing }
303 | | vfpdef { Just ($1, Nothing) }
304 |
305 | -- stmt: simple_stmt | compound_stmt
306 |
307 | stmt :: { [StatementSpan] }
308 | stmt
309 | : simple_stmt { $1 }
310 | | compound_stmt { [$1] }
311 |
312 | -- simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
313 |
314 | simple_stmt :: { [StatementSpan] }
315 | simple_stmt : small_stmts opt(';') 'NEWLINE' { reverse $1 }
316 |
317 | small_stmts :: { [StatementSpan] }
318 | small_stmts
319 | : small_stmt { [$1] }
320 | | small_stmts ';' small_stmt { $3 : $1 }
321 |
322 | {-
323 | small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
324 | import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
325 | -}
326 |
327 | small_stmt :: { StatementSpan }
328 | small_stmt
329 | : expr_stmt { $1 }
330 | | del_stmt { $1 }
331 | | pass_stmt { $1 }
332 | | flow_stmt { $1 }
333 | | import_stmt { $1 }
334 | | global_stmt { $1 }
335 | | nonlocal_stmt { $1 }
336 | | assert_stmt { $1 }
337 |
338 | -- expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*)
339 |
340 | expr_stmt :: { StatementSpan }
341 | expr_stmt
342 | : testlist_star_expr either(many_assign, augassign_yield_or_test_list)
343 | { makeAssignmentOrExpr $1 $2 }
344 |
345 | many_assign :: { [ExprSpan] }
346 | many_assign : many0(right('=', yield_or_test_list_star)) { $1 }
347 |
348 | yield_or_test_list :: { ExprSpan }
349 | yield_or_test_list : or(yield_expr,testlist) { $1 }
350 |
351 | yield_or_test_list_star :: { ExprSpan }
352 | yield_or_test_list_star : or(yield_expr,testlist_star_expr) { $1 }
353 |
354 | augassign_yield_or_test_list :: { (AssignOpSpan, ExprSpan) }
355 | augassign_yield_or_test_list : augassign yield_or_test_list { ($1, $2) }
356 |
357 | -- testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
358 |
359 | testlist_star_expr :: { ExprSpan }
360 | testlist_star_expr
361 | : test_list_star_rev opt_comma
362 | { makeTupleOrExpr (reverse $1) $2 }
363 |
364 | test_list_star_rev :: { [ExprSpan] }
365 | test_list_star_rev
366 | : or(test,star_expr) { [$1] }
367 | | test_list_star_rev ',' or(test,star_expr) { $3 : $1 }
368 |
369 | {-
370 | augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
371 | '<<=' | '>>=' | '**=' | '//=')
372 | -}
373 |
374 | augassign :: { AssignOpSpan }
375 | augassign
376 | : '+=' { AST.PlusAssign (getSpan $1) }
377 | | '-=' { AST.MinusAssign (getSpan $1) }
378 | | '*=' { AST.MultAssign (getSpan $1) }
379 | | '/=' { AST.DivAssign (getSpan $1) }
380 | | '%=' { AST.ModAssign (getSpan $1) }
381 | | '**=' { AST.PowAssign (getSpan $1) }
382 | | '&=' { AST.BinAndAssign (getSpan $1) }
383 | | '|=' { AST.BinOrAssign (getSpan $1) }
384 | | '^=' { AST.BinXorAssign (getSpan $1) }
385 | | '<<=' { AST.LeftShiftAssign (getSpan $1) }
386 | | '>>=' { AST.RightShiftAssign (getSpan $1) }
387 | | '//=' { AST.FloorDivAssign (getSpan $1) }
388 |
389 | -- del_stmt: 'del' exprlist
390 |
391 | del_stmt :: { StatementSpan }
392 | del_stmt : 'del' exprlist { AST.Delete $2 (spanning $1 $2) }
393 |
394 | -- pass_stmt: 'pass'
395 |
396 | pass_stmt :: { StatementSpan }
397 | pass_stmt : 'pass' { AST.Pass (getSpan $1) }
398 |
399 | -- flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
400 |
401 | flow_stmt :: { StatementSpan }
402 | flow_stmt
403 | : break_stmt { $1 }
404 | | continue_stmt { $1 }
405 | | return_stmt { $1 }
406 | | raise_stmt { $1 }
407 | | yield_stmt { $1 }
408 |
409 | -- break_stmt: 'break'
410 |
411 | break_stmt :: { StatementSpan }
412 | break_stmt : 'break' { AST.Break (getSpan $1) }
413 |
414 | -- continue_stmt: 'continue'
415 |
416 | continue_stmt :: { StatementSpan }
417 | continue_stmt : 'continue' { AST.Continue (getSpan $1) }
418 |
419 | -- return_stmt: 'return' [testlist]
420 |
421 | return_stmt :: { StatementSpan }
422 | return_stmt : 'return' optional_testlist { makeReturn $1 $2 }
423 |
424 | -- yield_stmt: yield_expr
425 |
426 | yield_stmt :: { StatementSpan }
427 | yield_stmt : yield_expr { StmtExpr $1 (getSpan $1) }
428 |
429 | -- raise_stmt: 'raise' [test ['from' test]]
430 |
431 | raise_stmt :: { StatementSpan }
432 | raise_stmt : 'raise' opt(pair(test, opt(right('from', test))))
433 | { AST.Raise (RaiseV3 $2) (spanning $1 $2) }
434 |
435 | -- import_stmt: import_name | import_from
436 |
437 | import_stmt :: { StatementSpan }
438 | import_stmt: or(import_name, import_from) { $1 }
439 |
440 | -- import_name: 'import' dotted_as_names
441 |
442 | import_name :: { StatementSpan }
443 | import_name : 'import' dotted_as_names { AST.Import $2 (spanning $1 $2) }
444 |
445 | {-
446 | # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
447 | import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
448 | 'import' ('*' | '(' import_as_names ')' | import_as_names))
449 | -}
450 |
451 | import_from :: { StatementSpan }
452 | import_from : 'from' import_module 'import' star_or_as_names
453 | { FromImport $2 $4 (spanning $1 $4) }
454 |
455 | import_module :: { ImportRelativeSpan }
456 | import_module: import_module_dots { makeRelative $1 }
457 |
458 | import_module_dots :: { [Either Token DottedNameSpan] }
459 | import_module_dots
460 | : '.' { [ Left $1 ] }
461 | | '...' { [ Left $1 ] }
462 | | dotted_name { [ Right $1 ] }
463 | | '.' import_module_dots { Left $1 : $2 }
464 | | '...' import_module_dots { Left $1 : $2 }
465 |
466 | star_or_as_names :: { FromItemsSpan }
467 | star_or_as_names
468 | : '*' { ImportEverything (getSpan $1) }
469 | | '(' import_as_names ')' { $2 }
470 | | import_as_names { $1 }
471 |
472 | -- import_as_name: NAME ['as' NAME]
473 | import_as_name :: { FromItemSpan }
474 | import_as_name
475 | : NAME optional_as_name { FromItem $1 $2 (spanning $1 $2) }
476 |
477 | -- dotted_as_name: dotted_name ['as' NAME]
478 |
479 | dotted_as_name :: { ImportItemSpan }
480 | dotted_as_name
481 | : dotted_name optional_as_name
482 | { ImportItem $1 $2 (spanning $1 $2) }
483 |
484 | -- import_as_names: import_as_name (',' import_as_name)* [',']
485 |
486 | import_as_names :: { FromItemsSpan }
487 | import_as_names : sepOptEndBy(import_as_name, ',') { FromItems $1 (getSpan $1) }
488 |
489 | -- dotted_as_names: dotted_as_name (',' dotted_as_name)*
490 |
491 | dotted_as_names :: { [ImportItemSpan] }
492 | dotted_as_names : sepBy(dotted_as_name,',') { $1 }
493 |
494 | -- dotted_name: NAME ('.' NAME)*
495 |
496 | dotted_name :: { DottedNameSpan }
497 | dotted_name : NAME many0(right('.', NAME)) { $1 : $2 }
498 |
499 | -- global_stmt: 'global' NAME (',' NAME)*
500 |
501 | global_stmt :: { StatementSpan }
502 | global_stmt : 'global' one_or_more_names { AST.Global $2 (spanning $1 $2) }
503 |
504 | one_or_more_names :: { [IdentSpan] }
505 | one_or_more_names: sepBy(NAME, ',') { $1 }
506 |
507 | -- nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
508 |
509 | nonlocal_stmt :: { StatementSpan }
510 | nonlocal_stmt : 'nonlocal' one_or_more_names { AST.NonLocal $2 (spanning $1 $2) }
511 |
512 | -- assert_stmt: 'assert' test [',' test]
513 |
514 | assert_stmt :: { StatementSpan }
515 | assert_stmt : 'assert' sepBy(test,',')
516 | { AST.Assert $2 (spanning $1 $2) }
517 |
518 | -- compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
519 |
520 | compound_stmt :: { StatementSpan }
521 | compound_stmt
522 | : if_stmt { $1 }
523 | | while_stmt { $1 }
524 | | for_stmt { $1 }
525 | | try_stmt { $1 }
526 | | with_stmt { $1 }
527 | | funcdef { $1 }
528 | | classdef { $1 }
529 | | decorated { $1 }
530 |
531 | -- if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
532 |
533 | if_stmt :: { StatementSpan }
534 | if_stmt : 'if' test ':' suite many0(elif) optional_else
535 | { Conditional (($2, $4):$5) $6 (spanning (spanning (spanning $1 $4) $5) $6) }
536 |
537 | elif :: { (ExprSpan, [StatementSpan]) }
538 | elif : 'elif' test ':' suite { ($2, $4) }
539 |
540 | optional_else :: { [StatementSpan] }
541 | optional_else
542 | : {- empty -} { [] }
543 | | 'else' ':' suite { $3 }
544 |
545 | -- while_stmt: 'while' test ':' suite ['else' ':' suite]
546 |
547 | while_stmt :: { StatementSpan }
548 | while_stmt
549 | : 'while' test ':' suite optional_else
550 | { AST.While $2 $4 $5 (spanning (spanning $1 $4) $5) }
551 |
552 | -- for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
553 |
554 | for_stmt :: { StatementSpan }
555 | for_stmt
556 | : 'for' exprlist 'in' testlist ':' suite optional_else
557 | { AST.For $2 $4 $6 $7 (spanning (spanning $1 $6) $7) }
558 |
559 | {-
560 | try_stmt: ('try' ':' suite
561 | ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite))
562 | -}
563 |
564 | try_stmt :: { StatementSpan }
565 | try_stmt : 'try' ':' suite handlers { makeTry $1 $3 $4 }
566 |
567 | handlers :: { ([HandlerSpan], [StatementSpan], [StatementSpan]) }
568 | handlers
569 | : one_or_more_except_clauses optional_else optional_finally { ($1, $2, $3) }
570 | | 'finally' ':' suite { ([], [], $3) }
571 |
572 | optional_finally :: { [StatementSpan] }
573 | optional_finally
574 | : {- empty -} { [] }
575 | | 'finally' ':' suite { $3 }
576 |
577 | one_or_more_except_clauses :: { [HandlerSpan] }
578 | one_or_more_except_clauses : many1(handler) { $1 }
579 |
580 | handler :: { HandlerSpan }
581 | handler : except_clause ':' suite { Handler $1 $3 (spanning $1 $3) }
582 |
583 | -- with_stmt: 'with' with_item (',' with_item)* ':' suite
584 |
585 | with_stmt :: { StatementSpan }
586 | with_stmt : 'with' sepOptEndBy(with_item, ',') ':' suite
587 | { AST.With $2 $4 (spanning $1 $4) }
588 |
589 | -- with_item: test ['as' expr]
590 |
591 | with_item :: { (ExprSpan, Maybe ExprSpan) }
592 | with_item: pair(test,opt(right('as',expr))) { $1 }
593 |
594 | -- except_clause: 'except' [test ['as' NAME]]
595 | -- XXX is this a bug in the grammar? In the online does the target is more complex than a NAME.
596 | -- see: http://docs.python.org/3.1/reference/compound_stmts.html#the-try-statement
597 |
598 | except_clause :: { ExceptClauseSpan }
599 | except_clause : 'except' opt(pair(test, optional_as_expr)) { ExceptClause $2 (spanning $1 $2) }
600 |
601 | optional_as_expr :: { Maybe ExprSpan}
602 | optional_as_expr: opt(right('as', test)) { $1 }
603 |
604 | optional_as_name :: { Maybe IdentSpan }
605 | optional_as_name: opt(right('as', NAME)) { $1 }
606 |
607 | -- suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
608 | -- Note: we don't have a newline before indent b/c it is redundant
609 |
610 | suite :: { [StatementSpan] }
611 | suite
612 | : simple_stmt { $1 }
613 | | {- no newline here! -} 'indent' many1(stmt) 'dedent' { concat $2 }
614 |
615 | -- test: or_test ['if' or_test 'else' test] | lambdef
616 |
617 | test :: { ExprSpan }
618 | test
619 | : or_test opt(test_if_cond) { makeConditionalExpr $1 $2 }
620 | | lambdef { $1 }
621 |
622 | test_if_cond :: { (ExprSpan, ExprSpan) }
623 | test_if_cond: 'if' or_test 'else' test { ($2, $4) }
624 |
625 | -- test_nocond: or_test | lambdef_nocond
626 |
627 | test_no_cond :: { ExprSpan }
628 | test_no_cond: or(or_test, lambdef_nocond) { $1 }
629 |
630 | -- lambdef: 'lambda' [varargslist] ':' test
631 |
632 | lambdef :: { ExprSpan }
633 | lambdef : 'lambda' opt_varargslist ':' test { AST.Lambda $2 $4 (spanning $1 $4) }
634 |
635 | -- lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
636 |
637 | lambdef_nocond :: { ExprSpan }
638 | lambdef_nocond : 'lambda' opt_varargslist ':' test_no_cond { AST.Lambda $2 $4 (spanning $1 $4) }
639 |
640 | opt_varargslist :: { [ParameterSpan] }
641 | opt_varargslist: opt(varargslist) { concat (maybeToList $1) }
642 |
643 | -- or_test: and_test ('or' and_test)*
644 |
645 | or_test :: { ExprSpan }
646 | or_test : and_test many0(pair(or_op,and_test)) { makeBinOp $1 $2 }
647 |
648 | or_op :: { OpSpan }
649 | or_op: 'or' { AST.Or (getSpan $1) }
650 |
651 | -- and_test: not_test ('and' not_test)*
652 |
653 | and_test :: { ExprSpan }
654 | and_test : not_test many0(pair(and_op, not_test)) { makeBinOp $1 $2 }
655 |
656 | and_op :: { OpSpan }
657 | and_op: 'and' { AST.And (getSpan $1) }
658 |
659 | -- not_test: 'not' not_test | comparison
660 |
661 | not_test :: { ExprSpan }
662 | not_test
663 | : 'not' not_test { UnaryOp (AST.Not (getSpan $1)) $2 (spanning $1 $2) }
664 | | comparison { $1 }
665 |
666 | -- comparison: expr (comp_op expr)*
667 |
668 | comparison :: { ExprSpan }
669 | comparison : expr many0(pair(comp_op, expr)) { makeBinOp $1 $2 }
670 |
671 | -- comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not'
672 |
673 | comp_op :: { OpSpan }
674 | comp_op
675 | : '<' { AST.LessThan (getSpan $1) }
676 | | '>' { AST.GreaterThan (getSpan $1) }
677 | | '==' { AST.Equality (getSpan $1) }
678 | | '>=' { AST.GreaterThanEquals (getSpan $1) }
679 | | '<=' { AST.LessThanEquals (getSpan $1) }
680 | | '!=' { AST.NotEquals (getSpan $1) }
681 | | 'in' { AST.In (getSpan $1) }
682 | | 'not' 'in' { AST.NotIn (spanning $1 $2) }
683 | | 'is' { AST.Is (getSpan $1) }
684 | | 'is' 'not' { AST.IsNot (spanning $1 $2) }
685 |
686 | -- star_expr: '*' expr
687 |
688 | star_expr :: { ExprSpan }
689 | star_expr : '*' expr { Starred $2 (spanning $1 $2) }
690 |
691 | -- expr: xor_expr ('|' xor_expr)*
692 |
693 | expr :: { ExprSpan }
694 | expr : xor_expr many0(pair(bar_op, xor_expr)) { makeBinOp $1 $2 }
695 |
696 | bar_op :: { OpSpan }
697 | bar_op: '|' { AST.BinaryOr (getSpan $1) }
698 |
699 | -- xor_expr: and_expr ('^' and_expr)*
700 |
701 | xor_expr :: { ExprSpan }
702 | xor_expr : and_expr many0(pair(hat_op, and_expr)) { makeBinOp $1 $2 }
703 |
704 | hat_op :: { OpSpan }
705 | hat_op: '^' { AST.Xor (getSpan $1) }
706 |
707 | -- and_expr: shift_expr ('&' shift_expr)*
708 |
709 | and_expr :: { ExprSpan }
710 | and_expr : shift_expr many0(pair(ampersand, shift_expr)) { makeBinOp $1 $2 }
711 |
712 | ampersand :: { OpSpan }
713 | ampersand: '&' { AST.BinaryAnd (getSpan $1) }
714 |
715 | -- shift_expr: arith_expr (('<<'|'>>') arith_expr)*
716 |
717 | shift_expr :: { ExprSpan }
718 | shift_expr: arith_expr many0(pair(shift_op, arith_expr)) { makeBinOp $1 $2 }
719 |
720 | shift_op :: { OpSpan }
721 | shift_op
722 | : '<<' { AST.ShiftLeft (getSpan $1) }
723 | | '>>' { AST.ShiftRight (getSpan $1) }
724 |
725 | -- arith_expr: term (('+'|'-') term)*
726 |
727 | arith_expr :: { ExprSpan }
728 | arith_expr: term many0(pair(arith_op, term)) { makeBinOp $1 $2 }
729 |
730 | arith_op :: { OpSpan }
731 | arith_op
732 | : '+' { AST.Plus (getSpan $1) }
733 | | '-' { AST.Minus (getSpan $1) }
734 |
735 | -- term: factor (('*'|'/'|'%'|'//') factor)*
736 |
737 | term :: { ExprSpan }
738 | term : factor many0(pair(mult_div_mod_op, factor)) { makeBinOp $1 $2 }
739 |
740 | mult_div_mod_op :: { OpSpan }
741 | mult_div_mod_op
742 | : '*' { AST.Multiply (getSpan $1) }
743 | | '/' { AST.Divide (getSpan $1) }
744 | | '%' { AST.Modulo (getSpan $1) }
745 | | '//' { AST.FloorDivide (getSpan $1) }
746 |
747 | -- factor: ('+'|'-'|'~') factor | power
748 |
749 | factor :: { ExprSpan }
750 | factor
751 | : or(arith_op, tilde_op) factor { UnaryOp $1 $2 (spanning $1 $2) }
752 | | power { $1 }
753 |
754 | tilde_op :: { OpSpan }
755 | tilde_op: '~' { AST.Invert (getSpan $1) }
756 |
757 | -- power: atom trailer* ['**' factor]
758 |
759 | power :: { ExprSpan }
760 | power : atom many0(trailer) opt(pair(exponent_op, factor))
761 | { makeBinOp (addTrailer $1 $2) (maybeToList $3) }
762 |
763 | exponent_op :: { OpSpan }
764 | exponent_op: '**' { AST.Exponent (getSpan $1) }
765 |
766 | {-
767 | atom: ('(' [yield_expr|testlist_comp] ')' |
768 | '[' [testlist_comp] ']' |
769 | '{' [dictorsetmaker] '}' |
770 | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
771 | -}
772 |
773 | atom :: { ExprSpan }
774 | atom : '(' yield_or_testlist_comp ')' { $2 (spanning $1 $3) }
775 | | list_atom { $1 }
776 | | dict_or_set_atom { $1 }
777 | | NAME { AST.Var $1 (getSpan $1) }
778 | | 'integer' { AST.Int (token_integer $1) (token_literal $1) (getSpan $1) }
779 | | 'float' { AST.Float (token_double $1) (token_literal $1) (getSpan $1) }
780 | | 'imaginary' { AST.Imaginary (token_double $1) (token_literal $1) (getSpan $1) }
781 | | many1('string') { AST.Strings (map token_literal $1) (getSpan $1) }
782 | | many1('bytestring') { AST.ByteStrings (map token_literal $1) (getSpan $1) }
783 | | many1('unicodestring') { AST.UnicodeStrings (map token_literal $1) (getSpan $1) }
784 | | '...' { AST.Ellipsis (getSpan $1) }
785 | | 'None' { AST.None (getSpan $1) }
786 | | 'True' { AST.Bool Prelude.True (getSpan $1) }
787 | | 'False' { AST.Bool Prelude.False (getSpan $1) }
788 |
789 | list_atom :: { ExprSpan }
790 | list_atom
791 | : '[' ']' { List [] (spanning $1 $2) }
792 | | '[' testlist_comp ']' { makeListForm (spanning $1 $3) $2 }
793 |
794 | dict_or_set_atom :: { ExprSpan }
795 | dict_or_set_atom
796 | : '{' '}' { Dictionary [] (spanning $1 $2) }
797 | | '{' dictorsetmaker '}' { $2 (spanning $1 $3) }
798 |
799 | yield_or_testlist_comp :: { SrcSpan -> ExprSpan }
800 | yield_or_testlist_comp
801 | : {- empty -} { Tuple [] }
802 | | yield_expr { Paren $1 }
803 | | testlist_comp { either Paren Generator $1 }
804 |
805 | -- testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
806 |
807 | testlist_comp :: { Either ExprSpan ComprehensionSpan }
808 | testlist_comp
809 | : testlist_star_expr { Left $1 }
810 | | or(test,star_expr) comp_for { Right (makeComprehension $1 $2) }
811 |
812 | -- trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
813 |
814 | trailer :: { Trailer }
815 | trailer
816 | : paren_arg_list { TrailerCall (fst $1) (snd $1) }
817 | | '[' subscriptlist ']' { TrailerSubscript $2 (spanning $1 $3) }
818 | | '.' NAME { TrailerDot $2 (getSpan $1) (spanning $1 $2) }
819 |
820 | -- subscriptlist: subscript (',' subscript)* [',']
821 |
822 | subscriptlist :: { [Subscript] }
823 | subscriptlist : sepOptEndBy(subscript, ',') { $1 }
824 |
825 | -- subscript: test | [test] ':' [test] [sliceop]
826 |
827 | subscript :: { Subscript }
828 | subscript
829 | : test { SubscriptExpr $1 (getSpan $1) }
830 | | opt(test) ':' opt(test) opt(sliceop)
831 | { SubscriptSlice $1 $3 $4 (spanning (spanning (spanning $1 $2) $3) $4) }
832 |
833 | -- sliceop: ':' [test]
834 |
835 | sliceop :: { Maybe ExprSpan }
836 | sliceop : ':' opt(test) { $2 }
837 |
838 | -- exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
839 |
840 | exprlist :: { [ExprSpan] }
841 | exprlist: sepOptEndBy(or(expr,star_expr), ',') { $1 }
842 |
843 | opt_comma :: { Maybe Token }
844 | opt_comma
845 | : {- empty -} { Nothing }
846 | | ',' { Just $1 }
847 |
848 | -- testlist: test (',' test)* [',']
849 |
850 | -- Some trickery here because the of the optional trailing comma, which
851 | -- could turn a normal expression into a tuple.
852 | -- Very occasionally, testlist is used to generate something which is not
853 | -- a tuple (such as the square bracket notation in list literals). Therefore
854 | -- it would seem like a good idea to not return a tuple in this case, but
855 | -- a list of expressions. However this would complicate a lot of code
856 | -- since we would have to carry around the optional comma information.
857 | -- I've decided to leave it as a tuple, and in special cases, unpack the
858 | -- tuple and pull out the list of expressions.
859 |
860 | testlist :: { ExprSpan }
861 | testlist : testlistrev opt_comma { makeTupleOrExpr (reverse $1) $2 }
862 |
863 | testlistrev :: { [ExprSpan] }
864 | testlistrev
865 | : test { [$1] }
866 | | testlistrev ',' test { $3 : $1 }
867 |
868 | {-
869 | dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
870 | (test (comp_for | (',' test)* [','])) )
871 | -}
872 |
873 | dictorsetmaker :: { SrcSpan -> ExprSpan }
874 | dictorsetmaker
875 | : test ':' test dict_rest { makeDictionary ($1, $3) $4 }
876 | | test set_rest { makeSet $1 $2 }
877 |
878 | dict_rest :: { Either CompForSpan [(ExprSpan, ExprSpan)] }
879 | dict_rest
880 | : comp_for { Left $1 }
881 | | zero_or_more_dict_mappings_rev opt_comma { Right (reverse $1) }
882 |
883 | zero_or_more_dict_mappings_rev :: { [(ExprSpan, ExprSpan)] }
884 | zero_or_more_dict_mappings_rev
885 | : {- empty -} { [] }
886 | | zero_or_more_dict_mappings_rev ',' test ':' test { ($3,$5) : $1 }
887 |
888 | set_rest :: { Either CompForSpan [ExprSpan] }
889 | set_rest
890 | : comp_for { Left $1 }
891 | | zero_or_more_comma_test_rev opt_comma { Right (reverse $1) }
892 |
893 | zero_or_more_comma_test_rev :: { [ExprSpan] }
894 | zero_or_more_comma_test_rev
895 | : {- empty -} { [] }
896 | | zero_or_more_comma_test_rev ',' test { $3 : $1 }
897 |
898 | -- classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
899 |
900 | classdef :: { StatementSpan }
901 | -- classdef: 'class' NAME optional_arg_list ':' suite
902 | classdef: 'class' NAME opt_paren_arg_list ':' suite
903 | { AST.Class $2 $3 $5 (spanning $1 $5) }
904 |
905 | optional_arg_list :: { [ArgumentSpan] }
906 | optional_arg_list: opt(arglist) { concat (maybeToList $1) }
907 |
908 | {-
909 | arglist: (argument ',')* (argument [',']
910 | |'*' test (',' argument)* [',' '**' test]
911 | |'**' test)
912 | -}
913 |
914 | {-
915 | We don't follow the grammar rules directly (though we do implement
916 | something equivalent). The reason is that there is ambiguity over
917 | the optional comma.
918 |
919 | It is probably okay to allow the optional comma even after the *, and
920 | ** forms. It seems more consistent to me.
921 | -}
922 |
923 | arglist :: { [ArgumentSpan] }
924 | arglist: sepOptEndBy(oneArgument,',') {% checkArguments $1 }
925 |
926 | oneArgument
927 | : '*' test { ArgVarArgsPos $2 (spanning $1 $2) }
928 | | '**' test { ArgVarArgsKeyword $2 (spanning $1 $2) }
929 | | argument { $1 }
930 |
931 | -- argument: test [comp_for] | test '=' test # Really [keyword '='] test
932 |
933 | argument :: { ArgumentSpan }
934 | argument
935 | : NAME '=' test { ArgKeyword $1 $3 (spanning $1 $3) }
936 | | test { ArgExpr $1 (getSpan $1) }
937 | | test comp_for
938 | { let span = spanning $1 $1 in ArgExpr (Generator (makeComprehension $1 $2) span) span }
939 |
940 | -- comp_iter: comp_for | comp_if
941 |
942 | comp_iter :: { CompIterSpan }
943 | comp_iter
944 | : comp_for { IterFor $1 (getSpan $1) }
945 | | comp_if { IterIf $1 (getSpan $1) }
946 |
947 | -- comp_for: 'for' exprlist 'in' or_test [comp_iter]
948 |
949 | comp_for :: { CompForSpan }
950 | comp_for
951 | : 'for' exprlist 'in' or_test opt(comp_iter)
952 | { CompFor $2 $4 $5 (spanning (spanning $1 $4) $5) }
953 |
954 | -- comp_if: 'if' test_nocond [comp_iter]
955 |
956 | comp_if :: { CompIfSpan }
957 | comp_if
958 | : 'if' test_no_cond opt(comp_iter)
959 | { CompIf $2 $3 (spanning (spanning $1 $2) $3) }
960 |
961 | -- encoding_decl: NAME
962 | -- Not used in the rest of the grammar!
963 |
964 | -- yield_expr: 'yield' [yield_arg]
965 |
966 | yield_expr :: { ExprSpan }
967 | yield_expr : 'yield' optional_yieldarg { AST.Yield $2 (spanning $1 $2) }
968 |
969 | optional_testlist :: { Maybe ExprSpan }
970 | optional_testlist: opt(testlist) { $1 }
971 |
972 | optional_yieldarg :: { Maybe YieldArgSpan }
973 | optional_yieldarg: opt(yieldarg) { $1 }
974 |
975 | -- yield_arg: 'from' test | testlist
976 |
977 | yieldarg :: { YieldArgSpan }
978 | yieldarg
979 | : 'from' test { YieldFrom $2 (spanning $1 $2) }
980 | | testlist { YieldExpr $1 }
981 |
982 | {
983 | -- Put additional Haskell code in here if needed.
984 | }
985 |
--------------------------------------------------------------------------------
/DATS/shared.dats:
--------------------------------------------------------------------------------
1 | #include "DATS/cli.dats"
2 | #include "DATS/count-loop.dats"
3 | #include "DATS/print.dats"
4 |
5 | staload "libats/ML/SATS/string.sats"
6 | staload "SATS/filetype.sats"
7 | staload "libats/ML/SATS/atspre.sats"
8 | staload "libats/ML/SATS/list0.sats"
9 | staload "libats/ML/SATS/basis.sats"
10 | staload EXTRA = "libats/ML/SATS/filebas.sats"
11 | staload "libats/ML/DATS/filebas_dirent.dats"
12 | staload "libats/libc/SATS/unistd.sats"
13 | staload _ = "libats/ML/DATS/atspre.dats"
14 | staload _ = "libats/ML/DATS/list0.dats"
15 | staload _ = "libats/ML/DATS/filebas.dats"
16 | staload "SATS/print.sats"
17 |
18 | #define nil list_nil
19 | #define :: list_cons
20 |
21 | val empty_file = let
22 | var f = @{ files = 0, blanks = 0, comments = 0, lines = 0 } : file
23 | in
24 | f
25 | end
26 |
27 | fn to_file(s : string, pre : Option(string)) : file =
28 | let
29 | var is_comment = case+ pre of
30 | | Some (x) => string_is_prefix(x, s)
31 | | None => false
32 | in
33 | if s = "" then
34 | @{ lines = 1, blanks = 1, comments = 0, files = 0 }
35 | else
36 | if is_comment then
37 | @{ lines = 1, blanks = 0, comments = 1, files = 0 }
38 | else
39 | @{ lines = 1, blanks = 0, comments = 0, files = 0 }
40 | end
41 |
42 | fn add_contents(x : source_contents, y : source_contents) : source_contents =
43 | let
44 | var next = @{ rust = x.rust + y.rust
45 | , haskell = x.haskell + y.haskell
46 | , ats = x.ats + y.ats
47 | , python = x.python + y.python
48 | , vimscript = x.vimscript + y.vimscript
49 | , elm = x.elm + y.elm
50 | , idris = x.idris + y.idris
51 | , madlang = x.madlang + y.madlang
52 | , tex = x.tex + y.tex
53 | , markdown = x.markdown + y.markdown
54 | , yaml = x.yaml + y.yaml
55 | , toml = x.toml + y.toml
56 | , cabal = x.cabal + y.cabal
57 | , happy = x.happy + y.happy
58 | , alex = x.alex + y.alex
59 | , go = x.go + y.go
60 | , html = x.html + y.html
61 | , css = x.css + y.css
62 | , scss = x.scss + y.scss
63 | , verilog = x.verilog + y.verilog
64 | , vhdl = x.vhdl + y.vhdl
65 | , c = x.c + y.c
66 | , purescript = x.purescript + y.purescript
67 | , futhark = x.futhark + y.futhark
68 | , brainfuck = x.brainfuck + y.brainfuck
69 | , ruby = x.ruby + y.ruby
70 | , julia = x.julia + y.julia
71 | , perl = x.perl + y.perl
72 | , sml = x.sml + y.sml
73 | , ocaml = x.ocaml + y.ocaml
74 | , agda = x.agda + y.agda
75 | , cobol = x.cobol + y.cobol
76 | , tcl = x.tcl + y.tcl
77 | , r = x.r + y.r
78 | , lua = x.lua + y.lua
79 | , cpp = x.cpp + y.cpp
80 | , lalrpop = x.lalrpop + y.lalrpop
81 | , header = x.header + y.header
82 | , sixten = x.sixten + y.sixten
83 | , dhall = x.dhall + y.dhall
84 | , ipkg = x.ipkg + y.ipkg
85 | , makefile = x.makefile + y.makefile
86 | , justfile = x.justfile + y.justfile
87 | , ion = x.ion + y.ion
88 | , bash = x.bash + y.bash
89 | , dash = x.dash + y.dash
90 | , hamlet = x.hamlet + y.hamlet
91 | , cassius = x.cassius + y.cassius
92 | , lucius = x.lucius + y.lucius
93 | , julius = x.julius + y.julius
94 | , mercury = x.mercury + y.mercury
95 | , yacc = x.yacc + y.yacc
96 | , lex = x.lex + y.lex
97 | , coq = x.coq + y.coq
98 | , jupyter = x.jupyter + y.jupyter
99 | , java = x.java + y.java
100 | , scala = x.scala + y.scala
101 | , erlang = x.erlang + y.erlang
102 | , elixir = x.elixir + y.elixir
103 | , pony = x.pony + y.pony
104 | , clojure = x.clojure + y.clojure
105 | , cabal_project = x.cabal_project + y.cabal_project
106 | , assembly = x.assembly + y.assembly
107 | , nix = x.nix + y.nix
108 | , php = x.php + y.php
109 | , javascript = x.javascript + y.javascript
110 | , kotlin = x.kotlin + y.kotlin
111 | , fsharp = x.fsharp + y.fsharp
112 | , fortran = x.fortran + y.fortran
113 | , swift = x.swift + y.swift
114 | , csharp = x.csharp + y.csharp
115 | , nim = x.nim + y.nim
116 | , cpp_header = x.cpp_header + y.cpp_header
117 | , elisp = x.elisp + y.elisp
118 | , plaintext = x.plaintext + y.plaintext
119 | , rakefile = x.rakefile + y.rakefile
120 | , llvm = x.llvm + y.llvm
121 | , autoconf = x.autoconf + y.autoconf
122 | , batch = x.batch + y.batch
123 | , powershell = x.powershell + y.powershell
124 | , m4 = x.m4 + y.m4
125 | , objective_c = x.objective_c + y.objective_c
126 | , automake = x.automake + y.automake
127 | , carp = x.carp + y.carp
128 | , shen = x.shen + y.shen
129 | , greencard = x.greencard + y.greencard
130 | , cmm = x.cmm + y.cmm
131 | , fluid = x.fluid + y.fluid
132 | , plutus = x.plutus + y.plutus
133 | , j = x.j + y.j
134 | , blodwen = x.blodwen + y.blodwen
135 | , crystal = x.crystal + y.crystal
136 | , racket = x.racket + y.racket
137 | , ada = x.ada + y.ada
138 | , isabelle = x.isabelle + y.isabelle
139 | , fstar = x.fstar + y.fstar
140 | , d = x.d + y.d
141 | , factor = x.factor + y.factor
142 | , scheme = x.scheme + y.scheme
143 | , chapel = x.chapel + y.chapel
144 | , pascal = x.pascal + y.pascal
145 | , ragel = x.ragel + y.ragel
146 | , xml = x.xml + y.xml
147 | , awk = x.awk + y.awk
148 | , sed = x.sed + y.sed
149 | , k = x.k + y.k
150 | , typescript = x.typescript + y.typescript
151 | , coffeescript = x.coffeescript + y.coffeescript
152 | , red = x.red + y.red
153 | , fish = x.fish + y.fish
154 | , vb = x.vb + y.vb
155 | , frege = x.frege + y.frege
156 | , dart = x.dart + y.dart
157 | , solidity = x.solidity + y.solidity
158 | , egison = x.egison + y.egison
159 | , zig = x.zig + y.zig
160 | , sql = x.sql + y.sql
161 | , felix = x.felix + y.felix
162 | , qsharp = x.qsharp + y.qsharp
163 | , oz = x.oz + y.oz
164 | , jai = x.jai + y.jai
165 | , zimpl = x.zimpl + y.zimpl
166 | , volt = x.volt + y.volt
167 | , cogent = x.cogent + y.cogent
168 | , clean = x.clean + y.clean
169 | , thrift = x.thrift + y.thrift
170 | , vala = x.vala + y.vala
171 | , apex = x.apex + y.apex
172 | , sas = x.sas + y.sas
173 | , nu = x.nu + y.nu
174 | , haxe = x.haxe + y.haxe
175 | , eiffel = x.eiffel + y.eiffel
176 | , tla = x.tla + y.tla
177 | , lean = x.lean + y.lean
178 | , io = x.io + y.io
179 | , squirrel = x.squirrel + y.squirrel
180 | , agdalib = x.agdalib + y.agdalib
181 | , cedille = x.cedille + y.cedille
182 | , raml = x.raml + y.raml
183 | , scribble = x.scribble + y.scribble
184 | , bibtex = x.bibtex + y.bibtex
185 | , csv = x.csv + y.csv
186 | , terraform = x.terraform + y.terraform
187 | , org = x.org + y.org
188 | , vagrantfile = x.vagrantfile + y.vagrantfile
189 | , glsl = x.glsl + y.glsl
190 | , dickinson = x.dickinson + y.dickinson
191 | , mirth = x.mirth + y.mirth
192 | , flix = x.flix + y.flix
193 | , jac = x.jac + y.jac
194 | , gdb = x.gdb + y.gdb
195 | , bqn = x.bqn + y.bqn
196 | } : source_contents
197 | in
198 | next
199 | end
200 |
201 | overload + with add_contents
202 |
203 | // This is the step function used when streaming directory contents.
204 | fn adjust_contents(sc_r : &source_contents >> source_contents, scf : pl_type) : void =
205 | let
206 | val () = case+ scf of
207 | | ~haskell n => sc_r.haskell := sc_r.haskell + n
208 | | ~ats n => sc_r.ats := sc_r.ats + n
209 | | ~rust n => sc_r.rust := sc_r.rust + n
210 | | ~markdown n => sc_r.markdown := sc_r.markdown + n
211 | | ~python n => sc_r.python := sc_r.python + n
212 | | ~vimscript n => sc_r.vimscript := sc_r.vimscript + n
213 | | ~yaml n => sc_r.yaml := sc_r.yaml + n
214 | | ~toml n => sc_r.toml := sc_r.toml + n
215 | | ~happy n => sc_r.happy := sc_r.happy + n
216 | | ~alex n => sc_r.alex := sc_r.alex + n
217 | | ~idris n => sc_r.idris := sc_r.idris + n
218 | | ~madlang n => sc_r.madlang := sc_r.madlang + n
219 | | ~elm n => sc_r.elm := sc_r.elm + n
220 | | ~c n => sc_r.c := sc_r.c + n
221 | | ~go n => sc_r.go := sc_r.go + n
222 | | ~cabal n => sc_r.cabal := sc_r.cabal + n
223 | | ~verilog n => sc_r.verilog := sc_r.verilog + n
224 | | ~vhdl n => sc_r.vhdl := sc_r.vhdl + n
225 | | ~html n => sc_r.html := sc_r.html + n
226 | | ~css n => sc_r.css := sc_r.css + n
227 | | ~scss n => sc_r.scss := sc_r.scss + n
228 | | ~purescript n => sc_r.purescript := sc_r.purescript + n
229 | | ~futhark n => sc_r.futhark := sc_r.futhark + n
230 | | ~brainfuck n => sc_r.brainfuck := sc_r.brainfuck + n
231 | | ~ruby n => sc_r.ruby := sc_r.ruby + n
232 | | ~julia n => sc_r.julia := sc_r.julia + n
233 | | ~tex n => sc_r.tex := sc_r.tex + n
234 | | ~perl n => sc_r.perl := sc_r.perl + n
235 | | ~sml n => sc_r.sml := sc_r.sml + n
236 | | ~ocaml n => sc_r.ocaml := sc_r.ocaml + n
237 | | ~agda n => sc_r.agda := sc_r.agda + n
238 | | ~cobol n => sc_r.cobol := sc_r.cobol + n
239 | | ~tcl n => sc_r.tcl := sc_r.tcl + n
240 | | ~r n => sc_r.r := sc_r.r + n
241 | | ~lua n => sc_r.lua := sc_r.lua + n
242 | | ~cpp n => sc_r.cpp := sc_r.cpp + n
243 | | ~lalrpop n => sc_r.lalrpop := sc_r.lalrpop + n
244 | | ~header n => sc_r.header := sc_r.header + n
245 | | ~sixten n => sc_r.sixten := sc_r.sixten + n
246 | | ~dhall n => sc_r.dhall := sc_r.dhall + n
247 | | ~ipkg n => sc_r.ipkg := sc_r.ipkg + n
248 | | ~justfile n => sc_r.justfile := sc_r.justfile + n
249 | | ~makefile n => sc_r.makefile := sc_r.makefile + n
250 | | ~ion n => sc_r.ion := sc_r.ion + n
251 | | ~bash n => sc_r.bash := sc_r.bash + n
252 | | ~dash n => sc_r.dash := sc_r.dash + n
253 | | ~hamlet n => sc_r.hamlet := sc_r.hamlet + n
254 | | ~cassius n => sc_r.cassius := sc_r.cassius + n
255 | | ~lucius n => sc_r.lucius := sc_r.lucius + n
256 | | ~julius n => sc_r.julius := sc_r.julius + n
257 | | ~mercury n => sc_r.mercury := sc_r.mercury + n
258 | | ~yacc n => sc_r.yacc := sc_r.yacc + n
259 | | ~lex n => sc_r.lex := sc_r.lex + n
260 | | ~coq n => sc_r.coq := sc_r.coq + n
261 | | ~jupyter n => sc_r.jupyter := sc_r.jupyter + n
262 | | ~java n => sc_r.java := sc_r.java + n
263 | | ~scala n => sc_r.scala := sc_r.scala + n
264 | | ~erlang n => sc_r.erlang := sc_r.erlang + n
265 | | ~elixir n => sc_r.elixir := sc_r.elixir + n
266 | | ~pony n => sc_r.pony := sc_r.pony + n
267 | | ~clojure n => sc_r.clojure := sc_r.clojure + n
268 | | ~cabal_project n => sc_r.cabal_project := sc_r.cabal_project + n
269 | | ~assembly n => sc_r.assembly := sc_r.assembly + n
270 | | ~nix n => sc_r.nix := sc_r.nix + n
271 | | ~php n => sc_r.php := sc_r.php + n
272 | | ~javascript n => sc_r.javascript := sc_r.javascript + n
273 | | ~kotlin n => sc_r.kotlin := sc_r.kotlin + n
274 | | ~fsharp n => sc_r.fsharp := sc_r.fsharp + n
275 | | ~fortran n => sc_r.fortran := sc_r.fortran + n
276 | | ~swift n => sc_r.swift := sc_r.swift + n
277 | | ~csharp n => sc_r.csharp := sc_r.csharp + n
278 | | ~nim n => sc_r.nim := sc_r.nim + n
279 | | ~cpp_header n => sc_r.cpp_header := sc_r.cpp_header + n
280 | | ~elisp n => sc_r.elisp := sc_r.elisp + n
281 | | ~plaintext n => sc_r.plaintext := sc_r.plaintext + n
282 | | ~rakefile n => sc_r.rakefile := sc_r.rakefile + n
283 | | ~llvm n => sc_r.llvm := sc_r.llvm + n
284 | | ~autoconf n => sc_r.autoconf := sc_r.autoconf + n
285 | | ~batch n => sc_r.batch := sc_r.batch + n
286 | | ~powershell n => sc_r.powershell := sc_r.powershell + n
287 | | ~m4 n => sc_r.m4 := sc_r.m4 + n
288 | | ~objective_c n => sc_r.objective_c := sc_r.objective_c + n
289 | | ~automake n => sc_r.automake := sc_r.automake + n
290 | | ~carp n => sc_r.carp := sc_r.carp + n
291 | | ~shen n => sc_r.shen := sc_r.shen + n
292 | | ~greencard n => sc_r.greencard := sc_r.greencard + n
293 | | ~cmm n => sc_r.cmm := sc_r.cmm + n
294 | | ~fluid n => sc_r.fluid := sc_r.fluid + n
295 | | ~plutus n => sc_r.plutus := sc_r.plutus + n
296 | | ~j n => sc_r.j := sc_r.j + n
297 | | ~blodwen n => sc_r.blodwen := sc_r.blodwen + n
298 | | ~crystal n => sc_r.crystal := sc_r.crystal + n
299 | | ~racket n => sc_r.racket := sc_r.racket + n
300 | | ~ada n => sc_r.ada := sc_r.ada + n
301 | | ~isabelle n => sc_r.isabelle := sc_r.isabelle + n
302 | | ~fstar n => sc_r.fstar := sc_r.fstar + n
303 | | ~d n => sc_r.d := sc_r.d + n
304 | | ~factor n => sc_r.factor := sc_r.factor + n
305 | | ~scheme n => sc_r.scheme := sc_r.scheme + n
306 | | ~chapel n => sc_r.chapel := sc_r.chapel + n
307 | | ~pascal n => sc_r.pascal := sc_r.pascal + n
308 | | ~ragel n => sc_r.ragel := sc_r.ragel + n
309 | | ~xml n => sc_r.xml := sc_r.xml + n
310 | | ~awk n => sc_r.awk := sc_r.awk + n
311 | | ~sed n => sc_r.sed := sc_r.sed + n
312 | | ~k n => sc_r.k := sc_r.k + n
313 | | ~typescript n => sc_r.typescript := sc_r.typescript + n
314 | | ~coffeescript n => sc_r.coffeescript := sc_r.coffeescript + n
315 | | ~red n => sc_r.red := sc_r.red + n
316 | | ~fish n => sc_r.fish := sc_r.fish + n
317 | | ~vb n => sc_r.vb := sc_r.vb + n
318 | | ~frege n => sc_r.frege := sc_r.frege + n
319 | | ~dart n => sc_r.dart := sc_r.dart + n
320 | | ~solidity n => sc_r.solidity := sc_r.solidity + n
321 | | ~egison n => sc_r.egison := sc_r.egison + n
322 | | ~zig n => sc_r.zig := sc_r.zig + n
323 | | ~sql n => sc_r.sql := sc_r.sql + n
324 | | ~felix n => sc_r.felix := sc_r.felix + n
325 | | ~qsharp n => sc_r.qsharp := sc_r.qsharp + n
326 | | ~oz n => sc_r.oz := sc_r.oz + n
327 | | ~jai n => sc_r.jai := sc_r.jai + n
328 | | ~zimpl n => sc_r.zimpl := sc_r.zimpl + n
329 | | ~volt n => sc_r.volt := sc_r.volt + n
330 | | ~cogent n => sc_r.cogent := sc_r.cogent + n
331 | | ~clean n => sc_r.clean := sc_r.clean + n
332 | | ~thrift n => sc_r.thrift := sc_r.thrift + n
333 | | ~vala n => sc_r.vala := sc_r.vala + n
334 | | ~apex n => sc_r.apex := sc_r.apex + n
335 | | ~sas n => sc_r.sas := sc_r.sas + n
336 | | ~nu n => sc_r.nu := sc_r.nu + n
337 | | ~haxe n => sc_r.haxe := sc_r.haxe + n
338 | | ~eiffel n => sc_r.eiffel := sc_r.eiffel + n
339 | | ~tla n => sc_r.tla := sc_r.tla + n
340 | | ~lean n => sc_r.lean := sc_r.lean + n
341 | | ~io n => sc_r.io := sc_r.io + n
342 | | ~squirrel n => sc_r.squirrel := sc_r.squirrel + n
343 | | ~agdalib n => sc_r.agdalib := sc_r.agdalib + n
344 | | ~cedille n => sc_r.cedille := sc_r.cedille + n
345 | | ~raml n => sc_r.raml := sc_r.raml + n
346 | | ~scribble n => sc_r.scribble := sc_r.scribble + n
347 | | ~bibtex n => sc_r.bibtex := sc_r.bibtex + n
348 | | ~csv n => sc_r.csv := sc_r.csv + n
349 | | ~terraform n => sc_r.terraform := sc_r.terraform + n
350 | | ~org n => sc_r.org := sc_r.org + n
351 | | ~vagrantfile n => sc_r.vagrantfile := sc_r.vagrantfile + n
352 | | ~glsl n => sc_r.glsl := sc_r.glsl + n
353 | | ~dickinson n => sc_r.dickinson := sc_r.dickinson + n
354 | | ~mirth n => sc_r.mirth := sc_r.mirth + n
355 | | ~flix n => sc_r.flix := sc_r.flix + n
356 | | ~jac n => sc_r.jac := sc_r.jac + n
357 | | ~gdb n => sc_r.gdb := sc_r.gdb + n
358 | | ~bqn n => sc_r.bqn := sc_r.bqn + n
359 | | ~unknown _ => ()
360 | in
361 | ()
362 | end
363 |
364 | fun match_keywords { m : nat | m <= 10 }(keys : list(string, m), word : string) : bool =
365 | list_foldright_cloref(keys, lam (next, acc) = acc || eq_string_string(next, word), false)
366 |
367 | // helper function for check_keywords
368 | fn step_keyword(size : file, pre : pl_type, word : string, ext : string) : pl_type =
369 | case+ pre of
370 | | unknown _ =>
371 | begin
372 | case+ ext of
373 | | "y" => let
374 | val _ = free(pre)
375 | var happy_keywords = "module" :: "import" :: nil
376 | in
377 | ifcase
378 | | match_keywords(happy_keywords, word) => happy(size)
379 | | let
380 | var yacc_keywords = "struct" :: "char" :: "int" :: nil
381 | in
382 | match_keywords(yacc_keywords, word)
383 | end => yacc(size)
384 | | _ => unknown
385 | end
386 | | "v" => let
387 | var _ = free(pre)
388 | var verilog_keywords = "endmodule" :: "posedge" :: "edge" :: "always" :: "wire" :: nil
389 | in
390 | ifcase
391 | | match_keywords(verilog_keywords, word) => verilog(size)
392 | | let
393 | var coq_keywords = "Qed"
394 | :: "Require"
395 | :: "Hypothesis"
396 | :: "Inductive" :: "Remark" :: "Lemma" :: "Proof" :: "Definition" :: "Theorem" :: nil
397 | in
398 | match_keywords(coq_keywords, word)
399 | end => coq(size)
400 | | _ => unknown
401 | end
402 | | "m" => let
403 | val _ = free(pre)
404 | var mercury_keywords = "module" :: "pred" :: nil
405 | in
406 | ifcase
407 | | match_keywords(mercury_keywords, word) => mercury(size)
408 | | let
409 | var objective_c_keywords = "unsigned" :: "nil" :: "nullable" :: "nonnull" :: nil
410 | in
411 | match_keywords(objective_c_keywords, word)
412 | end => objective_c(size)
413 | | _ => unknown
414 | end
415 | | _ => pre
416 | end
417 | | _ => pre
418 |
419 | // Function to disambiguate extensions such as .v (Coq and Verilog) and .m
420 | // (Mercury and Objective C). This should only be called when extensions are in
421 | // conflict, as it reads the whole file.
422 | fn check_keywords(s : string, size : file, ext : string) : pl_type =
423 | let
424 | var ref = fileref_open_opt(s, file_mode_r)
425 | in
426 | case+ ref of
427 | | ~Some_vt (x) => let
428 | var init: pl_type = unknown
429 | var viewstream = $EXTRA.streamize_fileref_word(x)
430 | var result = stream_vt_foldleft_cloptr(viewstream, init, lam (acc, next) => step_keyword(size, acc, next, ext))
431 | val _ = fileref_close(x)
432 | in
433 | result
434 | end
435 | | ~None_vt() => (bad_file(s) ; unknown)
436 | end
437 |
438 | fn freadc {l:addr}(pf : !bytes_v(l, BUFSZ) | inp : !FILEptr1, p : ptr(l), c : char) : size_t =
439 | let
440 | extern
441 | castfn as_fileref(x : !FILEptr1) :<> FILEref
442 |
443 | var n = $extfcall(size_t, "fread", p, sizeof, BUFSZ - 1, as_fileref(inp))
444 | val () = $UN.ptr0_set(ptr_add(p, n), c)
445 | in
446 | n
447 | end
448 |
449 | // Check shebang on scripts.
450 | //
451 | // TODO flexible parser that drops spaces as appropriate
452 | // TODO check magic number so as to avoid checking shebang of binary file
453 | // FIXME: instead of using fileref_get_line_string, read into a buffer!
454 | // 26 chars?
455 | fn check_shebang(s : string) : pl_type =
456 | let
457 | var ref = fileref_open_opt(s, file_mode_r)
458 | val str: string = case+ ref of
459 | | ~Some_vt (x) => let
460 | var s = strptr2string(fileref_get_line_string(x))
461 | val _ = fileref_close(x)
462 | in
463 | s
464 | end
465 | | ~None_vt() => (bad_file(s) ; "")
466 | in
467 | case+ str of
468 | | "#!/usr/bin/env ion" => ion(line_count(s, Some_vt("#")))
469 | | "#!/usr/bin/env bash" => bash(line_count(s, Some_vt("#")))
470 | | "#!/usr/bin/env sh" => dash(line_count(s, Some_vt("#")))
471 | | "#!/bin/bash" => bash(line_count(s, Some_vt("#")))
472 | | "#!/bin/sh" => dash(line_count(s, Some_vt("#")))
473 | | "#!/bin/sed" => sed(line_count(s, Some_vt("#")))
474 | | "#!python" => python(line_count(s, Some_vt("#")))
475 | | "#!python2" => python(line_count(s, Some_vt("#")))
476 | | "#!python3" => python(line_count(s, Some_vt("#")))
477 | | "#!/usr/bin/env python" => python(line_count(s, Some_vt("#")))
478 | | "#!/usr/bin/env python2" => python(line_count(s, Some_vt("#")))
479 | | "#!/usr/bin/env python3" => python(line_count(s, Some_vt("#")))
480 | | "#!/usr/bin/env perl" => perl(line_count(s, Some_vt("#")))
481 | | "#!/usr/bin/env perl6" => perl(line_count(s, Some_vt("#")))
482 | | "#!/usr/bin/perl" => perl(line_count(s, Some_vt("#")))
483 | | "#!/usr/bin/env stack" => haskell(line_count(s, Some_vt("--")))
484 | | "#!/usr/bin/env runhaskell" => haskell(line_count(s, Some_vt("--")))
485 | | "#!/usr/bin/env node" => javascript(line_count(s, None_vt))
486 | | "#!/usr/bin/env fish" => fish(line_count(s, Some_vt("#")))
487 | | "#!/usr/bin/Rscript" => r(line_count(s, None_vt))
488 | | _ => unknown
489 | end
490 |
491 | // Match based on filename (for makefiles, etc.)
492 | fn match_filename(s : string) : pl_type =
493 | let
494 | val (prf | str) = filename_get_base(s)
495 | var match = $UN.strptr2string(str)
496 | prval () = prf(str)
497 | in
498 | case+ match of
499 | | "Makefile" => makefile(line_count(s, Some_vt("#")))
500 | | "Makefile.tc" => makefile(line_count(s, Some_vt("#")))
501 | | "Makefile.common" => makefile(line_count(s, Some_vt("#")))
502 | | "Makefile.common_c" => makefile(line_count(s, Some_vt("#")))
503 | | "makefile" => makefile(line_count(s, Some_vt("#")))
504 | | "GNUmakefile" => makefile(line_count(s, Some_vt("#")))
505 | | "Justfile" => justfile(line_count(s, Some_vt("#")))
506 | | "justfile" => justfile(line_count(s, Some_vt("#")))
507 | | "Rakefile" => rakefile(line_count(s, None_vt))
508 | | "cabal.project.local" => cabal_project(line_count(s, Some_vt("--")))
509 | | "Vagrantfile" => vagrantfile(line_count(s, Some_vt("#")))
510 | | "Nukefile" => nu(line_count(s, Some_vt(";")))
511 | | "Pipfile" => toml(line_count(s, Some_vt("#")))
512 | | _ => check_shebang(s)
513 | end
514 |
515 | // Match based on file extension (assuming the file name is passed in as an
516 | // argument).
517 | fn prune_extension(s : string, file_proper : string) : pl_type =
518 | let
519 | val (prf | str) = filename_get_ext(s)
520 | val match: string = if strptr2ptr(str) > 0 then
521 | $UN.strptr2string(str)
522 | else
523 | ""
524 | prval () = prf(str)
525 | in
526 | case+ match of
527 | | "hs" => haskell(line_count(s, Some_vt("--")))
528 | | "cpphs" => haskell(line_count(s, Some_vt("--")))
529 | | "hsc" => haskell(line_count(s, Some_vt("--")))
530 | | "chs" => haskell(line_count(s, Some_vt("--")))
531 | | "hs-boot" => haskell(line_count(s, Some_vt("--")))
532 | | "hsig" => haskell(line_count(s, Some_vt("--")))
533 | | "gc" => greencard(line_count(s, Some_vt("--")))
534 | | "rs" => rust(line_count(s, Some_vt("//")))
535 | | "tex" => tex(line_count(s, Some_vt("%")))
536 | | "md" => markdown(line_count(s, None_vt))
537 | | "markdown" => markdown(line_count(s, None_vt))
538 | | "dats" => ats(line_count(s, Some_vt("//")))
539 | | "lats" => ats(line_count(s, Some_vt("//")))
540 | | "hats" => ats(line_count(s, Some_vt("//")))
541 | | "cats" => c(line_count(s, Some_vt("//")))
542 | | "sats" => ats(line_count(s, Some_vt("//")))
543 | | "py" => python(line_count(s, Some_vt("#")))
544 | | "fut" => futhark(line_count(s, Some_vt("--")))
545 | | "pl" => perl(line_count(s, None_vt))
546 | | "agda" => agda(line_count(s, Some_vt("--")))
547 | | "idr" => idris(line_count(s, Some_vt("--")))
548 | | "blod" => blodwen(line_count(s, Some_vt("--")))
549 | | "v" => check_keywords(s, line_count(s, Some_vt("--")), match)
550 | | "m" => check_keywords(s, line_count(s, None_vt), match)
551 | | "vhdl" => vhdl(line_count(s, None_vt))
552 | | "vhd" => vhdl(line_count(s, None_vt))
553 | | "go" => go(line_count(s, Some_vt("//")))
554 | | "vim" => vimscript(line_count(s, Some_vt("\"")))
555 | | "sml" => sml(line_count(s, None_vt))
556 | | "sig" => sml(line_count(s, None_vt))
557 | | "fun" => sml(line_count(s, None_vt))
558 | | "ml" => ocaml(line_count(s, None_vt))
559 | | "mli" => ocaml(line_count(s, None_vt))
560 | | "purs" => purescript(line_count(s, None_vt))
561 | | "elm" => elm(line_count(s, Some_vt("--")))
562 | | "mad" => madlang(line_count(s, Some_vt("#")))
563 | | "toml" => toml(line_count(s, Some_vt("#")))
564 | | "cabal" => cabal(line_count(s, Some_vt("--")))
565 | | "yml" => yaml(line_count(s, Some_vt("#")))
566 | | "yaml" => yaml(line_count(s, Some_vt("#")))
567 | | "y" => check_keywords(s, line_count(s, Some_vt("--")), match)
568 | | "ly" => happy(line_count(s, Some_vt("--")))
569 | | "yl" => happy(line_count(s, Some_vt("--")))
570 | | "ypp" => yacc(line_count(s, Some_vt("//")))
571 | | "x" => alex(line_count(s, Some_vt("--")))
572 | | "lx" => alex(line_count(s, Some_vt("--")))
573 | | "l" => lex(line_count(s, None_vt))
574 | | "lpp" => lex(line_count(s, None_vt))
575 | | "html" => html(line_count(s, None_vt))
576 | | "htm" => html(line_count(s, None_vt))
577 | | "css" => css(line_count(s, None_vt))
578 | | "scss" => scss(line_count(s, None_vt))
579 | | "vhdl" => vhdl(line_count(s, None_vt))
580 | | "vhd" => vhdl(line_count(s, None_vt))
581 | | "c" => c(line_count(s, Some_vt("//")))
582 | | "C" => cpp(line_count(s, Some_vt("//")))
583 | | "cmm" => cmm(line_count(s, Some_vt("//")))
584 | | "b" => brainfuck(line_count(s, None_vt))
585 | | "bf" => brainfuck(line_count(s, None_vt))
586 | | "rb" => ruby(line_count(s, None_vt))
587 | | "cob" => cobol(line_count(s, Some_vt("*>")))
588 | | "cbl" => cobol(line_count(s, Some_vt("*>")))
589 | | "cpy" => cobol(line_count(s, Some_vt("*>")))
590 | | "tcl" => tcl(line_count(s, Some_vt("#")))
591 | | "fl" => fluid(line_count(s, Some_vt("#")))
592 | | "r" => r(line_count(s, None_vt))
593 | | "R" => r(line_count(s, None_vt))
594 | | "lua" => lua(line_count(s, Some_vt("--")))
595 | | "cpp" => cpp(line_count(s, Some_vt("//")))
596 | | "ino" => cpp(line_count(s, Some_vt("//")))
597 | | "cc" => cpp(line_count(s, Some_vt("//")))
598 | | "lalrpop" => lalrpop(line_count(s, Some_vt("//")))
599 | | "h" => header(line_count(s, None_vt))
600 | | "vix" => sixten(line_count(s, Some_vt("--")))
601 | | "dhall" => dhall(line_count(s, Some_vt("--")))
602 | | "ipkg" => ipkg(line_count(s, Some_vt("--")))
603 | | "mk" => makefile(line_count(s, Some_vt("#")))
604 | | "hamlet" => hamlet(line_count(s, None_vt))
605 | | "cassius" => cassius(line_count(s, None_vt))
606 | | "lucius" => cassius(line_count(s, None_vt))
607 | | "julius" => julius(line_count(s, None_vt))
608 | | "jl" => julia(line_count(s, None_vt))
609 | | "ion" => ion(line_count(s, Some_vt("#")))
610 | | "bash" => bash(line_count(s, Some_vt("#")))
611 | | "ipynb" => jupyter(line_count(s, None_vt))
612 | | "java" => java(line_count(s, Some_vt("//")))
613 | | "scala" => scala(line_count(s, None_vt))
614 | | "erl" => erlang(line_count(s, None_vt))
615 | | "hrl" => erlang(line_count(s, None_vt))
616 | | "ex" => elixir(line_count(s, None_vt))
617 | | "exs" => elixir(line_count(s, None_vt))
618 | | "pony" => pony(line_count(s, None_vt))
619 | | "clj" => clojure(line_count(s, None_vt))
620 | | "s" => assembly(line_count(s, Some_vt(";")))
621 | | "S" => assembly(line_count(s, Some_vt(";")))
622 | | "asm" => assembly(line_count(s, Some_vt(";")))
623 | | "nix" => nix(line_count(s, None_vt))
624 | | "php" => php(line_count(s, None_vt))
625 | | "local" => match_filename(s)
626 | | "project" => cabal_project(line_count(s, Some_vt("--")))
627 | | "js" => javascript(line_count(s, Some_vt("//")))
628 | | "jsexe" => javascript(line_count(s, Some_vt("//")))
629 | | "kt" => kotlin(line_count(s, None_vt))
630 | | "kts" => kotlin(line_count(s, None_vt))
631 | | "fs" => fsharp(line_count(s, None_vt))
632 | | "f" => fortran(line_count(s, Some_vt("*")))
633 | | "F" => fortran(line_count(s, Some_vt("*")))
634 | | "for" => fortran(line_count(s, Some_vt("*")))
635 | | "f90" => fortran(line_count(s, Some_vt("*")))
636 | | "f95" => fortran(line_count(s, Some_vt("*")))
637 | | "swift" => swift(line_count(s, None_vt))
638 | | "csharp" => csharp(line_count(s, Some_vt("//")))
639 | | "cs" => csharp(line_count(s, Some_vt("//")))
640 | | "nim" => nim(line_count(s, None_vt))
641 | | "el" => elisp(line_count(s, Some_vt(";")))
642 | | "txt" => plaintext(line_count(s, None_vt))
643 | | "ll" => llvm(line_count(s, None_vt))
644 | | "in" => autoconf(line_count(s, Some_vt("#")))
645 | | "bat" => batch(line_count(s, None_vt))
646 | | "ps1" => powershell(line_count(s, None_vt))
647 | | "ac" => m4(line_count(s, None_vt))
648 | | "mm" => objective_c(line_count(s, Some_vt("//")))
649 | | "am" => automake(line_count(s, Some_vt("#")))
650 | | "carp" => carp(line_count(s, Some_vt(";")))
651 | | "pls" => plutus(line_count(s, None_vt))
652 | | "ijs" => j(line_count(s, Some_vt("NB")))
653 | | "cr" => crystal(line_count(s, Some_vt("#")))
654 | | "rkt" => racket(line_count(s, Some_vt("#")))
655 | | "adb" => ada(line_count(s, Some_vt("--")))
656 | | "ads" => ada(line_count(s, Some_vt("--")))
657 | | "thy" => isabelle(line_count(s, None_vt))
658 | | "fst" => fstar(line_count(s, Some_vt("//")))
659 | | "d" => d(line_count(s, Some_vt("//")))
660 | | "factor" => factor(line_count(s, Some_vt("!")))
661 | | "scm" => scheme(line_count(s, Some_vt(";")))
662 | | "ss" => scheme(line_count(s, Some_vt(";")))
663 | | "chpl" => chapel(line_count(s, Some_vt("//")))
664 | | "pas" => pascal(line_count(s, Some_vt("//")))
665 | | "rl" => ragel(line_count(s, None_vt))
666 | | "xml" => xml(line_count(s, None_vt))
667 | | "awk" => awk(line_count(s, Some_vt("#")))
668 | | "sed" => sed(line_count(s, Some_vt("#")))
669 | | "k" => k(line_count(s, Some_vt("/")))
670 | | "ts" => typescript(line_count(s, Some_vt("//")))
671 | | "coffee" => coffeescript(line_count(s, Some_vt("//")))
672 | | "red" => red(line_count(s, Some_vt(";")))
673 | | "vb" => vb(line_count(s, Some_vt("'")))
674 | | "frege" => frege(line_count(s, Some_vt("--")))
675 | | "dart" => dart(line_count(s, Some_vt("//")))
676 | | "sol" => solidity(line_count(s, Some_vt("//")))
677 | | "egi" => egison(line_count(s, Some_vt(";")))
678 | | "zig" => zig(line_count(s, Some_vt("//")))
679 | | "sql" => sql(line_count(s, Some_vt("--")))
680 | | "flx" => felix(line_count(s, Some_vt("//")))
681 | | "qs" => qsharp(line_count(s, Some_vt("//")))
682 | | "fish" => fish(line_count(s, Some_vt("#")))
683 | | "oz" => oz(line_count(s, Some_vt("%")))
684 | | "jai" => jai(line_count(s, Some_vt("//")))
685 | | "zpl" => zimpl(line_count(s, Some_vt("#")))
686 | | "volt" => volt(line_count(s, Some_vt("//")))
687 | | "cogent" => cogent(line_count(s, Some_vt("--")))
688 | | "icl" => clean(line_count(s, Some_vt("//")))
689 | | "dcl" => clean(line_count(s, Some_vt("//")))
690 | | "thrift" => thrift(line_count(s, Some_vt("//")))
691 | | "vala" => vala(line_count(s, Some_vt("//")))
692 | | "cls" => apex(line_count(s, Some_vt("//")))
693 | | "sas" => sas(line_count(s, Some_vt("%*")))
694 | | "nu" => nu(line_count(s, Some_vt(";")))
695 | | "hx" => haxe(line_count(s, Some_vt("//")))
696 | | "e" => eiffel(line_count(s, Some_vt("--")))
697 | | "tla" => tla(line_count(s, Some_vt("\\*")))
698 | | "lean" => lean(line_count(s, Some_vt("--")))
699 | | "io" => io(line_count(s, Some_vt("#")))
700 | | "nut" => squirrel(line_count(s, Some_vt("//")))
701 | | "agda-lib" => agda(line_count(s, None_vt))
702 | | "ced" => cedille(line_count(s, Some_vt("--")))
703 | | "raml" => raml(line_count(s, None_vt()))
704 | | "scrbl" => scribble(line_count(s, Some_vt(";")))
705 | | "bib" => bibtex(line_count(s, None_vt()))
706 | | "csv" => csv(line_count(s, None_vt()))
707 | | "tf" => terraform(line_count(s, Some_vt("#")))
708 | | "org" => org(line_count(s, Some_vt("#")))
709 | | "vert" => glsl(line_count(s, Some_vt("//")))
710 | | "frag" => glsl(line_count(s, Some_vt("//")))
711 | | "dck" => dickinson(line_count(s, Some_vt(";")))
712 | | "mth" => mirth(line_count(s, Some_vt("#")))
713 | | "flix" => flix(line_count(s, Some_vt("//")))
714 | | "jac" => jac(line_count(s, Some_vt("{.")))
715 | | "gdb" => gdb(line_count(s, Some_vt("#")))
716 | | "bqn" => bqn(line_count(s, Some_vt("#")))
717 | | "" => match_filename(s)
718 | | "sh" => match_filename(s)
719 | | "yamllint" => match_filename(s)
720 | | _ => unknown
721 | end
722 |
723 | // filter out directories containing artifacts
724 | fn bad_dir(s : string, excludes : List0(string)) : bool =
725 | case+ s of
726 | | "." => true
727 | | ".." => true
728 | | ".pijul" => true
729 | | "_darcs" => true
730 | | ".git" => true
731 | | ".hg" => true
732 | | ".fossil" => true
733 | | "build" => true
734 | | "target" => true
735 | | ".atspkg" => true
736 | | "nimcache" => true
737 | | "dist-newstyle" => true
738 | | "dist" => true
739 | | ".psc-package" => true
740 | | ".pulp-cache" => true
741 | | "bower_components" => true
742 | | "elm-stuff" => true
743 | | ".stack-work" => true
744 | | ".cabal-sandbox" => true
745 | | "node_modules" => true
746 | | ".egg-info" => true
747 | | ".lein-plugins" => true
748 | | ".sass-cache" => true
749 | | ".pyre" => true
750 | | ".vagrant" => true
751 | | _ => let
752 | val s0 = s + "/"
753 | in
754 | list_exists_cloref(excludes, lam x => x = s || x = s0)
755 | end
756 |
757 | fnx step_stream( acc : &source_contents >> source_contents
758 | , full_name : string
759 | , file_proper : string
760 | , excludes : List0(string)
761 | , verbose : bool
762 | ) : void =
763 | if test_file_isdir(full_name) > 0 then
764 | flow_stream(full_name, acc, excludes, verbose)
765 | else
766 | let
767 | val ft = prune_extension(full_name, file_proper)
768 | val () = if verbose then
769 | print!(print_file(ft, full_name))
770 | else
771 | ()
772 | val () = adjust_contents(acc, ft)
773 | in end
774 | and flow_stream(s : string, init : &source_contents >> source_contents, excludes : List0(string), verbose : bool) :
775 | void =
776 | let
777 | var files = $EXTRA.streamize_dirname_fname(s)
778 | var ffiles = stream_vt_filter_cloptr(files, lam x => not(bad_dir(x, excludes)))
779 | in
780 | if s != "." then
781 | let
782 | fun loop( ffiles : stream_vt(string)
783 | , init : &source_contents >> source_contents
784 | , f : (&source_contents >> source_contents, string, string, List0(string), bool) -> void
785 | ) : void =
786 | case+ !ffiles of
787 | | ~stream_vt_cons (next, nexts) => {
788 | val () = f(init, s + "/" + next, next, excludes, verbose)
789 | val () = loop(nexts, init, f)
790 | }
791 | | ~stream_vt_nil() => ()
792 | in
793 | loop(ffiles, init, step_stream)
794 | end
795 | else
796 | let
797 | fun loop( ffiles : stream_vt(string)
798 | , init : &source_contents >> source_contents
799 | , f : (&source_contents >> source_contents, string, string, List0(string), bool) -> void
800 | ) : void =
801 | case+ !ffiles of
802 | | ~stream_vt_cons (next, nexts) => {
803 | val () = f(init, next, next, excludes, verbose)
804 | val () = loop(nexts, init, f)
805 | }
806 | | ~stream_vt_nil() => ()
807 | in
808 | loop(ffiles, init, step_stream)
809 | end
810 | end
811 |
812 | fn empty_contents() : source_contents =
813 | let
814 | var isc = @{ rust = empty_file
815 | , haskell = empty_file
816 | , ats = empty_file
817 | , python = empty_file
818 | , vimscript = empty_file
819 | , elm = empty_file
820 | , idris = empty_file
821 | , madlang = empty_file
822 | , tex = empty_file
823 | , markdown = empty_file
824 | , yaml = empty_file
825 | , toml = empty_file
826 | , cabal = empty_file
827 | , happy = empty_file
828 | , alex = empty_file
829 | , go = empty_file
830 | , html = empty_file
831 | , css = empty_file
832 | , scss = empty_file
833 | , verilog = empty_file
834 | , vhdl = empty_file
835 | , c = empty_file
836 | , purescript = empty_file
837 | , futhark = empty_file
838 | , brainfuck = empty_file
839 | , ruby = empty_file
840 | , julia = empty_file
841 | , perl = empty_file
842 | , sml = empty_file
843 | , ocaml = empty_file
844 | , agda = empty_file
845 | , cobol = empty_file
846 | , tcl = empty_file
847 | , r = empty_file
848 | , lua = empty_file
849 | , cpp = empty_file
850 | , lalrpop = empty_file
851 | , header = empty_file
852 | , sixten = empty_file
853 | , dhall = empty_file
854 | , ipkg = empty_file
855 | , makefile = empty_file
856 | , justfile = empty_file
857 | , ion = empty_file
858 | , bash = empty_file
859 | , dash = empty_file
860 | , hamlet = empty_file
861 | , cassius = empty_file
862 | , lucius = empty_file
863 | , julius = empty_file
864 | , mercury = empty_file
865 | , yacc = empty_file
866 | , lex = empty_file
867 | , coq = empty_file
868 | , jupyter = empty_file
869 | , java = empty_file
870 | , scala = empty_file
871 | , erlang = empty_file
872 | , elixir = empty_file
873 | , pony = empty_file
874 | , clojure = empty_file
875 | , cabal_project = empty_file
876 | , assembly = empty_file
877 | , nix = empty_file
878 | , php = empty_file
879 | , javascript = empty_file
880 | , kotlin = empty_file
881 | , fsharp = empty_file
882 | , fortran = empty_file
883 | , swift = empty_file
884 | , csharp = empty_file
885 | , nim = empty_file
886 | , cpp_header = empty_file
887 | , elisp = empty_file
888 | , plaintext = empty_file
889 | , rakefile = empty_file
890 | , llvm = empty_file
891 | , autoconf = empty_file
892 | , batch = empty_file
893 | , powershell = empty_file
894 | , m4 = empty_file
895 | , objective_c = empty_file
896 | , automake = empty_file
897 | , carp = empty_file
898 | , shen = empty_file
899 | , greencard = empty_file
900 | , cmm = empty_file
901 | , fluid = empty_file
902 | , plutus = empty_file
903 | , j = empty_file
904 | , blodwen = empty_file
905 | , crystal = empty_file
906 | , racket = empty_file
907 | , ada = empty_file
908 | , isabelle = empty_file
909 | , fstar = empty_file
910 | , d = empty_file
911 | , factor = empty_file
912 | , scheme = empty_file
913 | , chapel = empty_file
914 | , pascal = empty_file
915 | , ragel = empty_file
916 | , xml = empty_file
917 | , awk = empty_file
918 | , sed = empty_file
919 | , k = empty_file
920 | , typescript = empty_file
921 | , coffeescript = empty_file
922 | , red = empty_file
923 | , fish = empty_file
924 | , vb = empty_file
925 | , frege = empty_file
926 | , dart = empty_file
927 | , solidity = empty_file
928 | , egison = empty_file
929 | , zig = empty_file
930 | , sql = empty_file
931 | , felix = empty_file
932 | , qsharp = empty_file
933 | , oz = empty_file
934 | , jai = empty_file
935 | , zimpl = empty_file
936 | , volt = empty_file
937 | , cogent = empty_file
938 | , clean = empty_file
939 | , thrift = empty_file
940 | , vala = empty_file
941 | , apex = empty_file
942 | , sas = empty_file
943 | , nu = empty_file
944 | , haxe = empty_file
945 | , eiffel = empty_file
946 | , tla = empty_file
947 | , lean = empty_file
948 | , io = empty_file
949 | , squirrel = empty_file
950 | , agdalib = empty_file
951 | , cedille = empty_file
952 | , raml = empty_file
953 | , scribble = empty_file
954 | , bibtex = empty_file
955 | , csv = empty_file
956 | , terraform = empty_file
957 | , org = empty_file
958 | , vagrantfile = empty_file
959 | , glsl = empty_file
960 | , dickinson = empty_file
961 | , mirth = empty_file
962 | , flix = empty_file
963 | , jac = empty_file
964 | , gdb = empty_file
965 | , bqn = empty_file
966 | } : source_contents
967 | in
968 | isc
969 | end
970 |
971 | fn map_stream( acc : &source_contents >> source_contents
972 | , includes : List0(string)
973 | , excludes : List0(string)
974 | , verbose : bool
975 | ) : void =
976 | let
977 | fun loop(includes : List0(string), acc : &source_contents >> source_contents) : void =
978 | case+ includes of
979 | | list_cons (next, nexts) => if test_file_exists(next) || test_file_isdir(next) < 0 || next = "" then
980 | (step_stream(acc, next, next, excludes, verbose) ; loop(nexts, acc))
981 | else
982 | maybe_err(next)
983 | | list_nil() => ()
984 | in
985 | loop(includes, acc)
986 | end
987 |
988 | fn step_list(s : string, excludes : List0(string)) : List0(string) =
989 | let
990 | var files = $EXTRA.streamize_dirname_fname(s)
991 | var ffiles = stream_vt_filter_cloptr(files, lam x => not(bad_dir(x, excludes) && test_file_isdir(s + "/" + x) > 0))
992 |
993 | fun stream2list(x : stream_vt(string)) : List0(string) =
994 | case+ !x of
995 | | ~stream_vt_cons (x, xs) => list_cons(s + "/" + x, stream2list(xs))
996 | | ~stream_vt_nil() => list_nil
997 | in
998 | stream2list(ffiles)
999 | end
1000 |
1001 | fn step_list_files(s : string, excludes : List0(string)) : List0(string) =
1002 | let
1003 | var files = $EXTRA.streamize_dirname_fname(s)
1004 | var ffiles = stream_vt_filter_cloptr(files, lam x => not(bad_dir(x, excludes)) && test_file_isdir(s + "/" + x) = 0)
1005 |
1006 | fun stream2list(x : stream_vt(string)) : List0(string) =
1007 | case+ !x of
1008 | | ~stream_vt_cons (x, xs) when s = "." => list_cons(x, stream2list(xs))
1009 | | ~stream_vt_cons (x, xs) => list_cons(s + "/" + x, stream2list(xs))
1010 | | ~stream_vt_nil() => list_nil
1011 | in
1012 | stream2list(ffiles)
1013 | end
1014 |
1015 | fn map_depth(xs : List0(string), excludes : List0(string)) : List0(string) =
1016 | let
1017 | fun loop(i : int, xs : List0(string), excludes : List0(string)) : List0(string) =
1018 | let
1019 | var xs0 = list0_filter(g0ofg1(xs), lam x => test_file_isdir(x) > 0)
1020 | in
1021 | case+ i of
1022 | | 0 => g1ofg0(list0_mapjoin(xs0, lam x => if not(bad_dir(x, excludes)) then
1023 | g0ofg1(step_list(x, excludes))
1024 | else
1025 | list0_nil))
1026 | | _ => g1ofg0(list0_mapjoin(xs0, lam x => let
1027 | var ys = step_list(x, excludes)
1028 | var zs = step_list_files(x, excludes)
1029 | in
1030 | if not(bad_dir(x, excludes)) then
1031 | g0ofg1(loop(i - 1, ys, excludes)) + g0ofg1(zs)
1032 | else
1033 | if x = "." && i = 3 then
1034 | g0ofg1(loop(i - 1, ys, excludes)) + g0ofg1(zs)
1035 | else
1036 | list0_nil
1037 | end))
1038 | end
1039 | in
1040 | loop(3, xs, excludes)
1041 | end
1042 |
--------------------------------------------------------------------------------