Created
October 12, 2018 14:30
-
-
Save richardjgowers/46dc6650d80f36ca39c426531db9053e to your computer and use it in GitHub Desktop.
For scipy issue 3168
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import glob\n", | |
"import subprocess\n", | |
"import re\n", | |
"import os" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def run_gf(fortran_code):\n", | |
" filename = 'tmp.f'\n", | |
" \n", | |
" with open(filename, 'w') as out:\n", | |
" out.write('\\n'.join(fortran_code))\n", | |
" \n", | |
" proc = subprocess.run('gfortran -fimplicit-none {}'.format(filename),\n", | |
" shell=True,\n", | |
" stderr=subprocess.PIPE, stdout=subprocess.PIPE)\n", | |
"\n", | |
" os.remove(filename)\n", | |
" \n", | |
" return proc\n", | |
" \n", | |
"\n", | |
"def grab_error_variables(stderr): \n", | |
" err_vars = []\n", | |
" for line in stderr:\n", | |
" if not line.startswith('Error: Symbol'):\n", | |
" continue\n", | |
" err_var =line.split(\"'\")[1].upper()\n", | |
" if not err_var in err_vars:\n", | |
" err_vars.append(err_var)\n", | |
" \n", | |
" return err_vars\n", | |
"\n", | |
"def grab_dimension_vars(fortran_code):\n", | |
" # returns mapping of var to its dimension declaration\n", | |
" dimension_vars = {}\n", | |
" \n", | |
" for line in fortran_code:\n", | |
" if not line.lstrip().startswith(('DIMENSION', '1 ', '2 ', '3 ')):\n", | |
" continue\n", | |
" hits = re.findall(r'([\\w\\d]+\\(.+?\\))', line)\n", | |
" for h in hits:\n", | |
" root = h.split('(')[0]\n", | |
" dimension_vars[root] = h\n", | |
"\n", | |
" return dimension_vars\n", | |
"\n", | |
"def grab_leading_whitespace(fortran_code):\n", | |
" # find the amount of leading whitespace\n", | |
" return re.search('(\\s+)', fortran_code[0]).groups()[0]\n", | |
"\n", | |
"def is_integer(var):\n", | |
" # apply fortran's implicit typing rules\n", | |
" return var.startswith(('I', 'J', 'K', 'L', 'M', 'N'))\n", | |
"\n", | |
"def split_subroutines(fortran_code):\n", | |
" starts = [i for i, l in enumerate(fortran_code)\n", | |
" if l.lstrip().startswith('SUBROUTINE')]\n", | |
" starts.append(None)\n", | |
" return [fortran_code[i:j]\n", | |
" for i, j in zip(starts[:-1], starts[1:])]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"LINE_LIMIT = 72\n", | |
"\n", | |
"def update_file(filename):\n", | |
" # slurp file\n", | |
" with open(filename, 'r') as inf:\n", | |
" raw = inf.readlines()\n", | |
" \n", | |
" \n", | |
" # split into subroutines\n", | |
" subroutines = split_subroutines(raw)\n", | |
" new_subs = []\n", | |
" \n", | |
" for sub in subroutines:\n", | |
" # process each subroutine\n", | |
" cp = run_gf(sub)\n", | |
" \n", | |
" stderr = cp.stderr.decode().split('\\n')\n", | |
" err_vars = grab_error_variables(stderr)\n", | |
" dimension_vars = grab_dimension_vars(sub)\n", | |
" ws = grab_leading_whitespace(sub)\n", | |
"\n", | |
" integers = []\n", | |
" floats = []\n", | |
" for var in err_vars:\n", | |
" if var in dimension_vars:\n", | |
" var = dimension_vars[var]\n", | |
" \n", | |
" varlist = integers if is_integer(var) else floats\n", | |
" varstart = 'INTEGER :: ' if is_integer(var) else 'REAL :: '\n", | |
" \n", | |
" if (varlist and\n", | |
" len(varlist[-1] + ', ' + var) < LINE_LIMIT):\n", | |
" varlist[-1] += ', ' + var\n", | |
" else:\n", | |
" varlist.append(ws + varstart + var)\n", | |
"\n", | |
" new_subs.append(sub[0])\n", | |
" new_subs.append(ws + 'IMPLICIT NONE\\n')\n", | |
" for i in integers:\n", | |
" new_subs.append(i + '\\n')\n", | |
" for f in floats:\n", | |
" new_subs.append(f + '\\n')\n", | |
" new_subs.extend(l for l in sub[1:]\n", | |
" if not l.lstrip().startswith(('DIMENSION', '1 ', '2 ', '3 ')))\n", | |
" \n", | |
" with open(filename, 'w') as out:\n", | |
" out.write(''.join(new_subs))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"for f in glob.glob('*.f'):\n", | |
" update_file(f)" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.5" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment