diff --git a/.github/workflows/pretty.yml b/.github/workflows/pretty.yml new file mode 100644 index 0000000000..f2c1fd7614 --- /dev/null +++ b/.github/workflows/pretty.yml @@ -0,0 +1,19 @@ +name: Pretty + +on: + push: + + pull_request: + + workflow_dispatch: + +jobs: + docs: + name: Code formatting + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Count + run: ./mfc.sh format diff diff --git a/toolchain/bootstrap/format.sh b/toolchain/bootstrap/format.sh index d6aea99deb..d61c65df46 100644 --- a/toolchain/bootstrap/format.sh +++ b/toolchain/bootstrap/format.sh @@ -1,11 +1,40 @@ #!/bin/bash -log "Formatting MFC with fprettify..." +log "MFC format..." -fprettify ${@:-src} --exclude "src/*/autogen" --recursive --silent \ - --indent 4 --c-relations --enable-replacements --enable-decl \ - --whitespace-comma 1 --whitespace-multdiv 1 --whitespace-plusminus 1 \ - --case 1 1 1 1 --strict-indent +opts="--recursive --silent --indent 4 --c-relations --enable-replacements --enable-decl --whitespace-comma 0 --whitespace-multdiv 0 --whitespace-plusminus 1 --case 1 1 1 1 --strict-indent --line-length 1000" + +if [ "$1" == "diff" ]; then + log "Checking format diff..." + shift + + # Indent acc directives + out_indent="" + fn="" + for filename in src/*/*.f*; do + out_indent+=$(python3 toolchain/indenter.py "$filename" "diff") + done + echo out_indent + echo ${out_indent} + exit 0 + + # Check prettify out + out_prettify=$(fprettify ${@:-src} --exclude "src/*/autogen" $opts -s -d) + if [ -z "${out_prettify}" ] && [ -z "${out_indent}" ]; then + echo "Already pretty!" + exit 0 + else + error "Not pretty, run ./mfc.sh format" + exit 1 + fi +fi + +# Indent acc directives +for filename in src/*/*.f*; do + python3 toolchain/indenter.py "$filename" +done + +fprettify ${@:-src} --exclude "src/*/autogen" $opts ret="$?" if [ "$ret" != '0' ]; then @@ -15,4 +44,4 @@ if [ "$ret" != '0' ]; then exit 1 fi -ok "MFC has been fprettify'ied." \ No newline at end of file +ok "MFC format complete." diff --git a/toolchain/indenter.py b/toolchain/indenter.py new file mode 100755 index 0000000000..0499f3ad7a --- /dev/null +++ b/toolchain/indenter.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +import sys +import os +import filecmp + +def main(): + num_args = len(sys.argv) + if num_args != 2 or num_args !=3: + AssertionError('Invalid number of arguments, found ', num_args) + if num_args == 3 and str(sys.argv[2]) != "diff": + AssertionError('Invalid third argument, ', sys.argv[2]) + + infile = str(sys.argv[1]) + outfile = infile+".new" + + adjust_indentation(infile, outfile) + if num_args == 2: + print('replacing',infile,'with',outfile) + os.replace(outfile,infile) + if num_args == 3: + same = filecmp.cmp(outfile,infile) + if not same: + print(infile) + print('different!') + # os.remove(outfile) + +def adjust_indentation(input_file, output_file): + startingchar='!$acc' + startingloop1='!$acc parallel loop' + startingloop2='!$acc loop' + max_empty_lines=4 + + with open(input_file, 'r') as file_in, open(output_file, 'w') as file_out: + lines = file_in.readlines() + + # this makes sure !$acc lines that have line continuations get indented at proper level + for kk in range(10): + # loop through file + for i in range(len(lines)): + if lines[i].lstrip().startswith(startingchar) and i + 1 < len(lines): + j = i + 1 + empty_lines = 0 + # look down to see how to indent a line + while j < len(lines) and empty_lines < max_empty_lines: + # if the following line starts with [end, else, contains], skip to looking up + if lines[j].lstrip().startswith('end') or \ + lines[j].lstrip().startswith('contains') or \ + lines[j].lstrip().startswith('else'): + empty_lines = max_empty_lines + # skip empty lines + elif lines[j].strip() == '': + empty_lines += 1 + # indent acc lines + elif not lines[j].lstrip().startswith(startingchar): + indent = len(lines[j]) - len(lines[j].lstrip()) + lines[i] = ' ' * indent + lines[i].lstrip() + break + j += 1 + # if looking down just finds empty lines, start looking up for indendation level + if empty_lines == max_empty_lines: + k = i - 1 + while k >= 0: + # if line above is not empty + if lines[k].strip() != '': + # if line 2 above ends with line continuation, indent at that level + if lines[k-1].strip().endswith('&'): + indent = len(lines[k-1]) - len(lines[k-1].lstrip()) + # else indent at level of line above + else: + indent = len(lines[k]) - len(lines[k].lstrip()) + lines[i] = ' ' * indent + lines[i].lstrip() + break + k -= 1 + + # remove empty lines following an acc loop directive + i = 0 + while i < len(lines): + if (lines[i].lstrip().startswith(startingloop1) or \ + lines[i].lstrip().startswith(startingloop2)) and \ + i+1 < len(lines) and lines[i+1].strip() == '': + file_out.write(lines[i]) + i +=2 + else: + file_out.write(lines[i]) + i += 1 + +if __name__ == "__main__": + main()