Skip to content

Instantly share code, notes, and snippets.

@richardjgowers
Created October 12, 2018 14:30
Show Gist options
  • Save richardjgowers/46dc6650d80f36ca39c426531db9053e to your computer and use it in GitHub Desktop.
Save richardjgowers/46dc6650d80f36ca39c426531db9053e to your computer and use it in GitHub Desktop.
For scipy issue 3168
Display the source blob
Display the rendered blob
Raw
{
"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