├── .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 | [![Build Status](https://travis-ci.org/vmchale/polyglot.svg?branch=master)](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 | Screenshot of sample output 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 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
ToolLanguageTime
polyglotATS134.6 ms
locRust139.6 ms
sccGo225.4 ms
tokeiRust262.6 ms
goclocGo923.9 ms
clocPerl5.610 s
enryGo6.926 s
linguistRuby20.16 s
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 = "" 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 = "
LanguageFilesLinesCodeCommentsBlanks
" 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 | --------------------------------------------------------------------------------