irpf90/src/preprocessed_text.py

928 lines
29 KiB
Python
Raw Normal View History

2020-01-27 18:22:35 +01:00
#!/usr/bin/env python3
2009-09-23 12:51:27 +02:00
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
2013-07-01 13:12:37 +02:00
# Copyright (C) 2009 Anthony SCEMAMA
2009-09-23 12:51:27 +02:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
2013-07-01 13:12:37 +02:00
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
2009-09-23 12:51:27 +02:00
2020-01-27 18:43:22 +01:00
from irpf90_t import *
from regexps import *
import error
from command_line import command_line
from util import *
2009-09-02 20:45:53 +02:00
# Local regular expressions
re_endif = re.compile("end\s+if")
re_elseif = re.compile("else\s+if")
re_enddo = re.compile("end\s+do")
2011-10-21 09:10:40 +02:00
re_endtype= re.compile("end\s+type")
re_endmodule = re.compile("end\s+module")
2009-09-02 20:45:53 +02:00
re_endselect = re.compile("end\s+select")
2014-04-02 23:01:33 +02:00
re_endinterface = re.compile("end\s+interface")
2009-09-02 20:45:53 +02:00
# Local variables
Free_form = 0
Fixed_form = 1
######################################################################
2009-09-29 15:27:52 +02:00
# Dictionary of simple statements
simple_dict = {
"subroutine": Subroutine ,
"begin_shell": Begin_shell ,
"end_shell": End_shell ,
2009-12-09 20:26:09 +01:00
"begin_template": Begin_template ,
"end_template": End_template ,
"subst": Subst ,
2009-09-29 15:27:52 +02:00
"end_doc": End_doc ,
"begin_provider": Begin_provider ,
"&begin_provider": Cont_provider ,
"end_provider": End_provider ,
"assert": Assert ,
"touch": Touch ,
2010-03-29 20:43:00 +02:00
"soft_touch": SoftTouch ,
2009-09-29 15:27:52 +02:00
"provide": Provide ,
2011-03-03 15:46:21 +01:00
"no_dep": NoDep ,
2009-09-29 15:27:52 +02:00
"free": Free ,
"irp_if": Irp_If ,
"irp_else": Irp_Else ,
"irp_endif": Irp_Endif ,
"irp_read": Irp_read ,
"irp_write": Irp_write ,
"use": Use ,
"do": Do ,
"if": If ,
"case": Case ,
"elseif": Elseif ,
"else": Else ,
"enddo": Enddo ,
"endif": Endif ,
"endselect": End_select ,
"end": End ,
"include": Include ,
"call": Call ,
"continue": Continue ,
"return": Return ,
"implicit": Implicit ,
"save": Declaration ,
"function": Function ,
"recursive": Function ,
}
2009-09-02 20:45:53 +02:00
def get_type (i, filename, line, is_doc):
'''Find the type of a text line'''
2010-10-02 23:42:55 +02:00
assert type(i) == int
assert type(filename) == str
assert type(line) == str
assert type(is_doc) == bool
2009-09-02 20:45:53 +02:00
2014-04-02 23:01:33 +02:00
# add support for interface block
has_interface = False
2009-09-02 20:45:53 +02:00
line = line.rstrip()
2012-12-07 15:12:10 +01:00
line = line.replace("$IRP_ALIGN",command_line.align)
2009-09-02 20:45:53 +02:00
lower_line0 = line.lstrip().lower()
2012-12-07 15:12:10 +01:00
lower_line = lower_line0.replace("!"," ! ")
2009-09-02 20:45:53 +02:00
# Replacements
lower_line = re_elseif.sub("elseif",lower_line)
lower_line = re_enddo.sub("enddo",lower_line)
2011-10-21 09:10:40 +02:00
lower_line = re_endtype.sub("endtype",lower_line)
lower_line = re_endmodule.sub("endmodule",lower_line)
2009-09-02 20:45:53 +02:00
lower_line = re_endif.sub("endif",lower_line)
lower_line = re_endselect.sub("endselect",lower_line)
2014-04-02 23:01:33 +02:00
lower_line = re_endinterface.sub("endinterface",lower_line)
2012-12-07 15:12:10 +01:00
2009-09-02 20:45:53 +02:00
for c in """()'"[]""":
2012-11-15 12:00:43 +01:00
lower_line = lower_line.replace(c," "+c+" ")
2009-09-02 20:45:53 +02:00
buffer = lower_line.split()
if len(buffer) == 0:
return [ Empty_line(i,line,filename) ], is_doc
firstword = buffer[0]
if firstword.isdigit():
assert len(buffer) > 1
buffer = buffer[1:]
firstword = buffer[0]
# Identify line
2014-04-02 23:01:33 +02:00
if firstword == "endinterface":
has_interface = False
return [ Simple_line (i,line,filename) ], False
if firstword == "interface" or has_interface:
has_interface = True
return [ Simple_line (i,line,filename) ], False
2009-09-02 20:45:53 +02:00
if firstword == "end_doc":
return [ End_doc (i,line,filename) ], False
if firstword == "begin_doc":
return [ Begin_doc (i,line,filename) ], True
2018-12-14 09:50:27 +01:00
if firstword == "program":
return [ Program (i,line,filename) ], False
2009-09-02 20:45:53 +02:00
if is_doc:
return [ Doc (i,line,filename) ], is_doc
2011-04-09 23:45:50 +02:00
if firstword in simple_dict:
2009-09-29 15:27:52 +02:00
return [ simple_dict[firstword](i,line,filename) ], is_doc
2013-07-01 13:12:37 +02:00
2009-09-29 15:27:52 +02:00
if firstword in [ "select", "selectcase" ]:
2011-10-03 11:47:33 +02:00
return [ Select(i,line,filename) ] , is_doc
2009-09-29 15:27:52 +02:00
2009-09-02 20:45:53 +02:00
if len(lower_line0) > 4:
if firstword[0] == '#':
result = [ Simple_line(i,line,filename) ]
2013-07-01 13:12:37 +02:00
error.warn ( result[0] ,
2009-09-02 20:45:53 +02:00
"""irpf90 may not work with preprocessor directives. You can use
Irp_if ... Irp_else ... Irp_endif
instead of
#ifdef ... #else ... #endif""" )
return result, is_doc
if firstword.startswith("case("):
return [ Case(i,line,filename) ], is_doc
if lower_line0[1:5] == "$omp":
2009-09-02 20:45:53 +02:00
return [ Openmp(i,line,filename) ], is_doc
elif lower_line0[1:5] in ["dec$", "dir$"] and command_line.directives:
return [ Directive(i,line,filename) ], is_doc
2012-11-27 01:12:16 +01:00
elif lower_line0[1:3] == "$ ":
return [ Openmp(i,line,filename) ], is_doc
2009-09-02 20:45:53 +02:00
if re_decl.match(lower_line) is not None:
if "function" in buffer[1:3]:
return [ Function (i,line,filename) ], is_doc
else:
return [ Declaration (i,line,filename) ], is_doc
2009-09-29 15:27:52 +02:00
# Detect errors
if firstword == "dowhile":
error.fail( Do(i,line,filename) , "'do while' should be in 2 words." )
2013-07-01 13:12:37 +02:00
2009-09-02 20:45:53 +02:00
return [ Simple_line(i,line,filename) ], is_doc
######################################################################
def get_text(lines,filename):
'''Read the input file and transform it to labeled lines'''
2010-10-02 23:42:55 +02:00
assert type(filename) == str
assert type(lines) == list
2009-09-02 20:45:53 +02:00
result = []
is_doc = False
for i,line in enumerate(lines):
line, is_doc = get_type(i+1,filename,line,is_doc)
result += line
return result
######################################################################
def execute_shell(text):
'''Execute the embedded shell scripts'''
def fail(l,a,b): error.fail(l,"In Begin_Shell, %s '%s'"%(a,b))
inside = False
result = []
for line in text:
if inside:
2010-10-02 23:42:55 +02:00
if type(line) == Begin_shell:
2009-09-02 20:45:53 +02:00
error.fail(line,"Nested Begin_shell")
2010-10-02 23:42:55 +02:00
elif type(line) == End_shell:
2009-09-02 20:45:53 +02:00
inside = False
# Write script file
scriptname = "%s%s_shell_%d"%(irpdir,line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
2009-09-02 20:45:53 +02:00
scriptname = "%s_shell_%d"%(line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
# Execute shell
import os
pipe = os.popen("%s < %s"%(shell,scriptname),'r')
lines = pipe.readlines()
pipe.close()
result += get_text(lines,scriptname)
os.remove(scriptname)
2009-09-02 20:45:53 +02:00
else:
script.append(line.text+'\n')
else:
2010-10-02 23:42:55 +02:00
if type(line) == Begin_shell:
2009-09-02 20:45:53 +02:00
inside = True
begin = line.i
script = []
# Find shell executable
buffer = line.text.split('[')
if len(buffer) > 2:
fail(line,"Too many",'[')
elif len(buffer) < 2:
fail(line,"Missing",'[')
buffer = buffer[1]
buffer = buffer.split(']')
if len(buffer) > 2:
fail(line,"Too many",']')
elif len(buffer) < 2:
fail(line,"Missing",']')
shell = buffer[0].strip()
2010-10-02 23:42:55 +02:00
elif type(line) == End_shell:
2009-09-02 20:45:53 +02:00
error.fail(line,"Begin_shell missing")
else:
result.append(line)
return result
2009-12-09 20:26:09 +01:00
######################################################################
def execute_templates(text):
'''Execute the templates'''
def fail(l,a,b): error.fail(l,"In %s, %s"%(a,b))
def get_variables(line):
buffer = line.text.split('[',1)
if len(buffer)<2:
fail(line,"Subst","Syntax error")
buffer = buffer[1].replace(']','')
buffer = buffer.split(',')
2020-01-27 18:22:35 +01:00
return ['$%s'%(x.strip()) for x in buffer]
2009-12-09 20:26:09 +01:00
TEMPLATE = 1
SUBST = 2
inside = 0
result = []
for line in text:
if inside == 0:
2010-10-02 23:42:55 +02:00
if type(line) == Begin_template:
2009-12-09 20:26:09 +01:00
script = []
inside = TEMPLATE
script = "template = \"\"\"\n"
else:
result.append(line)
elif inside == TEMPLATE:
2010-10-02 23:42:55 +02:00
if type(line) == Begin_template:
2009-12-09 20:26:09 +01:00
fail(line,"template", "Nested Begin_Template")
2010-10-02 23:42:55 +02:00
elif type(line) == End_template:
2009-12-09 20:26:09 +01:00
fail(line,"template","Missing Subst")
2010-10-02 23:42:55 +02:00
elif type(line) == Subst:
2009-12-09 20:26:09 +01:00
inside = SUBST
script += "\"\"\"\n"
variables = get_variables(line)
script += "v = []\n"
subst = ""
else:
script += line.text+"\n"
else: # inside == SUBST
2010-10-02 23:42:55 +02:00
if type(line) == Begin_template:
2009-12-09 20:26:09 +01:00
fail(line,"subst","Nested Begin_template")
2010-10-02 23:42:55 +02:00
elif type(line) == Subst:
2009-12-09 20:26:09 +01:00
fail(line,"subst","Subst already defined")
2010-10-02 23:42:55 +02:00
elif type(line) == End_template:
2009-12-09 20:26:09 +01:00
inside = 0
subst = subst.rstrip()
if subst[-2:] == ';;':
subst = subst[:-2]
for s in subst.split(';;'):
2020-01-27 18:22:35 +01:00
buffer = [x.strip() for x in s.split(';')]
2009-12-09 20:26:09 +01:00
if len(buffer) != len(variables):
fail(line,"subst","%d variables defined, and %d substitutions"%(len(variables),len(buffer)))
script += "v.append( { \\\n"
for t,v in zip(variables,buffer):
script += ' "%s": """%s""" ,\n'%(t,v)
script += "} )\n"
script += "for d in v:\n t0 = str(template)\n"
for v in variables:
script += " t0 = t0.replace('%s',d['%s'])\n"%(v,v)
2020-01-27 18:50:24 +01:00
script += " print(t0)\n"
2009-12-09 20:26:09 +01:00
# Write script file
scriptname = "%s%s_template_%d"%(irpdir,line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
scriptname = "%s_template_%d"%(line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
# Execute shell
import os
2023-10-19 17:50:35 +02:00
pipe = os.popen("python3 < %s"%(scriptname),'r')
2009-12-09 20:26:09 +01:00
lines = pipe.readlines()
pipe.close()
result += get_text(lines,scriptname)
os.remove(scriptname)
else:
subst += line.text+'\n'
return result
2009-09-02 20:45:53 +02:00
######################################################################
def form(text):
'''Find if the text is in fixed form or in free form'''
2010-10-02 23:42:55 +02:00
assert type(text) == list
2009-09-02 20:45:53 +02:00
if len(text) == 0:
return Free_form
assert isinstance(text[0],Line)
re2 = re.compile(r"^\s*[!#]")
re3 = re.compile(r"^\s*[^ 0-9]+")
for line in text:
if type(line) in [ Empty_line, Doc, Openmp, Directive ]:
2009-09-02 20:45:53 +02:00
pass
else:
if len(line.text) > 5:
test = line.text[0:5]
if test[0] in "Cc#!*":
pass
else:
if re2.match(test) is None and \
re3.match(test) is not None:
return Free_form
2009-09-03 17:44:00 +02:00
if line.text.rstrip()[-1] == '&':
return Free_form
2013-07-01 13:12:37 +02:00
return Fixed_form
2009-09-02 20:45:53 +02:00
2009-12-09 16:48:48 +01:00
######################################################################
def add_operators(text):
2017-09-18 15:14:18 +02:00
re_incr = re.compile(r"(\s*)(.*)(\+=)(.*$)", re.S)
re_decr = re.compile(r"(\s*)(.*)(-=)(.*$)", re.S)
re_mult = re.compile(r"(\s*)(.*)(\*=)(.*$)", re.S)
re_incr_if = re.compile(r"(.*)(\))(\s*)(.*)(\+=)(.*$)", re.S)
re_decr_if = re.compile(r"(.*)(\))(\s*)(.*)(-=)(.*$)", re.S)
re_mult_if = re.compile(r"(.*)(\))(\s*)(.*)(\*=)(.*$)", re.S)
2009-12-09 16:48:48 +01:00
'''Change additional operators'''
result = []
for line in text:
buffer = line.text
2015-11-26 16:50:03 +01:00
ls = buffer.strip()
if ls.startswith('print ') or \
ls.startswith('print*') or \
ls.startswith('write('):
2017-09-18 15:14:18 +02:00
pass
elif buffer.lstrip().startswith("if "):
if "+=" in buffer:
line.text = re.sub(re_incr_if, r'\1\2\4=\4+(\6)', buffer)
elif "-=" in buffer:
line.text = re.sub(re_incr_if, r'\1\2\4=\4-(\6)', buffer)
elif "*=" in buffer:
line.text = re.sub(re_incr_if, r'\1\2\4=\4*(\6)', buffer)
else:
if "+=" in buffer:
line.text = re.sub(re_incr, r'\1\2=\2+(\4)', buffer)
elif "-=" in buffer:
line.text = re.sub(re_decr, r'\1\2=\2-(\4)', buffer)
elif "*=" in buffer:
line.text = re.sub(re_mult, r'\1\2=\2*(\4)', buffer)
2009-12-09 16:48:48 +01:00
result.append(line)
return result
2009-09-02 20:45:53 +02:00
######################################################################
def remove_comments(text,form):
'''Remove all comments'''
result = []
def remove_after_bang(line):
match = re_comment.match(line)
if match is None:
return line
else:
return re_comment.split(line)[1].rstrip()
2013-07-01 13:12:37 +02:00
2009-09-02 20:45:53 +02:00
if form == Free_form:
for line in text:
if type(line) in [ Openmp, Doc, Directive] :
2009-09-02 20:45:53 +02:00
result.append(line)
2010-10-02 23:42:55 +02:00
elif type(line) == Empty_line:
2009-09-02 20:45:53 +02:00
pass
else:
newline = line.text.lstrip()
if newline == "" or newline[0] == "!":
pass
else:
line.text = remove_after_bang(line.text)
result.append(line)
return result
else:
for line in text:
if type(line) in [ Openmp, Doc, Directive ]:
2009-09-02 20:45:53 +02:00
result.append(line)
2010-10-02 23:42:55 +02:00
elif type(line) == Empty_line:
2009-09-02 20:45:53 +02:00
pass
else:
newline = line.text.lstrip()
if newline == "" or newline[0] == "!":
pass
else:
line.text = remove_after_bang(line.text)
if line.text[0] in "#123456789 ":
result.append(line)
2009-09-02 20:45:53 +02:00
return result
######################################################################
def remove_continuation(text,form):
'''Removes continuation lines'''
result = []
buffer = ""
number = 0
2009-09-03 17:44:00 +02:00
t = None
2009-09-02 20:45:53 +02:00
if form == Free_form:
for line in text:
if line.text[-1] == '&':
buffer = "%s%s\n"%(buffer,line.text)
2009-09-02 20:45:53 +02:00
if number == 0:
2009-09-03 17:44:00 +02:00
t = type(line)
2009-09-02 20:45:53 +02:00
number = line.i
else:
if number != 0:
2009-09-03 17:44:00 +02:00
newline = t(number, \
"%s%s"%(buffer,line.text), \
2009-09-03 17:44:00 +02:00
line.filename)
line = newline
2009-09-02 20:45:53 +02:00
number = 0
buffer = ""
result.append(line)
else:
rev_text = list(text)
rev_text.reverse()
for line in rev_text:
is_continuation = False
2010-10-02 23:42:55 +02:00
if type(line) == Simple_line:
2009-09-02 20:45:53 +02:00
if len(line.text) >= 6:
if line.text[5] != ' ':
is_continuation = True
if is_continuation:
buffer = "&\n%s %s %s"%(line.text[:5],line.text[6:],buffer)
2009-09-02 20:45:53 +02:00
else:
line.text = line.text+buffer
result.insert(0,line)
buffer = ""
return result
2013-07-01 13:12:37 +02:00
2009-09-03 00:46:11 +02:00
######################################################################
def irp_simple_statements(text):
'''Processes simple statements'''
def process_irp_rw(line,rw,t):
2010-10-02 23:42:55 +02:00
assert type(line) == t
2009-09-03 00:46:11 +02:00
buffer = line.text.split()
if len(buffer) == 2:
dummy, variable = buffer
num = "0"
elif len(buffer) == 3:
dummy, variable, num = buffer
else:
error.fail(line,"Error in IRP_%s statement"%(rw,))
2009-09-25 16:50:11 +02:00
variable = variable.lower()
2009-09-03 00:46:11 +02:00
i = line.i
f = line.filename
txt = line.text.lstrip()
result = [
Empty_line(i,"!",f),
2009-09-08 18:20:20 +02:00
t(i,"! >>> %s"%(txt,),variable ),
2009-09-04 15:11:42 +02:00
Provide_all(i," call %ser_%s('%s')"%(rw,variable,num),f),
Empty_line(i,"! >>> END %s "%(txt,),f ),
Empty_line(line.i,"!",f),
2009-09-03 00:46:11 +02:00
]
return result
2013-07-01 13:12:37 +02:00
2009-09-03 00:46:11 +02:00
def process_irp_read (line):
2010-10-02 23:42:55 +02:00
assert type(line) == Irp_read
2009-09-03 00:46:11 +02:00
return process_irp_rw(line,'read' ,Irp_read )
def process_irp_write(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Irp_write
2009-09-03 00:46:11 +02:00
return process_irp_rw(line,'writ' ,Irp_write)
def process_return(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Return
2017-09-18 15:19:59 +02:00
if command_line.do_debug:
2009-09-04 15:11:42 +02:00
newline = Simple_line(line.i," call irp_leave(irp_here)",line.filename)
2009-09-03 00:46:11 +02:00
result = [newline, line]
else:
result = [ line ]
return result
def debug_conditions(line):
'''Find condition in assert statement for debug'''
2010-10-02 23:42:55 +02:00
assert type(line) == Assert
2009-09-03 00:46:11 +02:00
match = re_test.search(line.text)
2009-09-25 15:04:54 +02:00
result = []
if match is not None:
2009-09-03 00:46:11 +02:00
matches = [ match.group(1).strip(), match.group(3).strip() ]
for m in matches:
ok = m != "" # not empty
ok = ok and not m.isdigit() # not a digit
ok = ok and "'" not in m # not a string
ok = ok and m.count('(') == m.count(')') # balanced parenthesis
if ok:
2009-09-04 15:11:42 +02:00
result.append ( Simple_line (line.i, " print *, '%s = ', %s"%(m,m), line.filename) )
result.append ( Simple_line (line.i, " print *, ''", line.filename) )
2009-09-03 00:46:11 +02:00
return result
2013-07-01 13:12:37 +02:00
2009-09-03 00:46:11 +02:00
def process_assert(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Assert
2009-09-03 00:46:11 +02:00
if command_line.do_assert:
2015-03-16 14:55:35 +01:00
if '(' not in line.text or ')' not in line.text:
error.fail(line,"Syntax error in ASSERT statement (parentheses)")
2009-09-09 16:59:43 +02:00
condition = "(%s"%(line.text.split('(',1)[1])
2009-09-03 00:46:11 +02:00
if condition == "":
error.fail(line,"Error in Assert statement")
condition_str = condition.replace("'","''")
i = line.i
f = line.filename
txt = line.text.strip()
result = [
Empty_line(i, "!", f),
Empty_line(i, "! >>> %s"%(txt,), f),
2009-09-04 15:11:42 +02:00
If (i, " if (.not.%s) then"%(condition,), f),
Simple_line(i, " print *, irp_here//': Assert failed:'", f),
Simple_line(i, " print *, ' file: %s, line: %d'"%(f,i), f),
Simple_line(i, " print *, '%s'"%(condition_str,), f),
2009-09-03 00:46:11 +02:00
] + debug_conditions(line) + [
2009-09-04 15:11:42 +02:00
Simple_line(i, " stop 1", f),
Endif (i, " endif", f),
Empty_line(i, "! <<< END %s"%(txt,), f),
Empty_line(i, "!", f)
2009-09-03 00:46:11 +02:00
]
else:
result = []
return result
def process_end(line):
2009-09-03 00:46:11 +02:00
'''Set irp_here variable in provider block'''
2009-09-25 15:22:46 +02:00
line.text = "end"
2017-09-18 15:19:59 +02:00
if command_line.do_debug:
2009-09-03 00:46:11 +02:00
i = line.i
f = line.filename
result = [
2009-09-04 15:11:42 +02:00
Simple_line(i," call irp_leave(irp_here)", f),
2009-09-03 00:46:11 +02:00
line
]
else:
result = [ line ]
return result
def process_begin_provider(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Begin_provider
2010-05-19 19:01:05 +02:00
buffer = line.lower.replace('['," ")
buffer = buffer.replace(']',"")
buffer = buffer.split(',')
if len(buffer) < 2:
error.fail(line,"Error in Begin_provider statement")
2010-05-19 19:01:05 +02:00
varname = buffer[1].strip()
length = len(varname)
i = line.i
f = line.filename
2009-09-09 16:59:43 +02:00
result = [ Begin_provider(i,line.text, (f,varname)),
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,varname), f) ]
2017-09-18 15:19:59 +02:00
if command_line.do_debug:
result += [
2009-09-04 15:11:42 +02:00
Simple_line(i," call irp_enter(irp_here)", f),
]
return result
2009-09-09 16:59:43 +02:00
def process_cont_provider(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Cont_provider
2010-05-19 19:01:05 +02:00
buffer = line.lower.replace('['," ")
2009-09-09 16:59:43 +02:00
buffer = buffer.replace(']',"")
buffer = buffer.split(',')
if len(buffer) < 2:
error.fail(line,"Error in Cont_provider statement")
2010-05-19 19:01:05 +02:00
varname = buffer[1].strip()
2009-09-09 16:59:43 +02:00
i = line.i
f = line.filename
return [ Cont_provider(i,line.text,(f,varname)) ]
def process_subroutine(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Subroutine
2009-09-04 18:37:10 +02:00
subname = find_subname(line)
length = len(subname)
i = line.i
f = line.filename
result = [ line,
2009-09-16 15:59:13 +02:00
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,subname), f) ]
2017-09-18 15:19:59 +02:00
if command_line.do_debug:
result += [
2014-05-23 22:03:23 +02:00
Simple_line(i," call irp_enter_f(irp_here)", f),
]
return result
def process_function(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Function
2009-09-04 18:37:10 +02:00
subname = find_subname(line)
length = len(subname)
i = line.i
f = line.filename
result = [ line,
2009-09-16 15:59:13 +02:00
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,subname), f) ]
2017-09-18 15:19:59 +02:00
if command_line.do_debug:
result += [
2014-05-23 22:03:23 +02:00
Simple_line(i," call irp_enter_f(irp_here)", f),
]
return result
def process_program(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Program
2010-05-19 19:01:05 +02:00
program_name = line.lower.split()[1]
2013-07-01 13:12:37 +02:00
temp = [ Program(0,"program irp_program",program_name) ]
if command_line.do_profile:
temp += [ Simple_line(0,"call irp_init_timer()",line.filename) ]
2014-10-08 22:56:54 +02:00
if command_line.do_openmp:
temp += [ Simple_line(0," call irp_init_locks_%s()"%(irp_id),line.filename) ]
temp += [ Call(0," call %s"%(program_name),line.filename) ]
if command_line.do_profile:
temp += [ Simple_line(0,"call irp_print_timer()",line.filename) ]
temp += [ Simple_line(0," call irp_finalize_%s()"%(irp_id),line.filename) ]
temp += [ End(0,"end program",line.filename) ]
result = temp + \
process_subroutine( Subroutine(line.i,"subroutine %s"%(program_name,),line.filename) )
return result
2009-09-03 00:46:11 +02:00
d = { Irp_read : process_irp_read,
Irp_write : process_irp_write,
Return : process_return,
Assert : process_assert,
End : process_end,
Begin_provider : process_begin_provider,
2009-09-09 16:59:43 +02:00
Cont_provider : process_cont_provider,
End_provider : process_end,
Subroutine : process_subroutine,
Function : process_function,
Program : process_program,
2009-09-03 00:46:11 +02:00
}
result = []
for line in text:
buffer = [ line ]
2011-04-09 23:45:50 +02:00
for t in d:
2010-10-02 23:42:55 +02:00
if type(line) == t:
2009-09-03 00:46:11 +02:00
buffer = d[t](line)
break
result += buffer
return result
2013-07-01 13:12:37 +02:00
######################################################################
def change_includes(text):
2009-09-03 16:52:38 +02:00
'''Deals with include files'''
result = []
for line in text:
2010-10-02 23:42:55 +02:00
if type(line) == Include:
txt = line.text.replace('"',"'").split("'")
if len(txt) != 3:
2020-01-27 18:22:35 +01:00
print(txt)
error.fail(line,"Error in include statement")
2013-12-11 14:00:27 +01:00
directory = (("./"+line.filename).rsplit('/',1)[0]+'/')[2:]
if directory == "":
filename = txt[1].strip()
else:
filename = directory+txt[1].strip()
try:
file = open(filename,'r')
file.close()
result.append(Include(line.i,"! include '%s'"%filename,filename))
2009-09-04 15:11:42 +02:00
result += create_preprocessed_text(filename)
except IOError:
result.append(Declaration(line.i,line.text,line.filename))
else:
result.append(line)
return result
2009-09-03 16:52:38 +02:00
######################################################################
def process_old_style_do(text):
'''Changes old-style do loops to new style'''
2010-10-02 23:42:55 +02:00
assert type(text) == list
2009-09-03 17:44:00 +02:00
def change_matching_enddo(begin,number):
for i in range(begin+1,len(text)):
line = text[i]
2009-09-05 15:37:23 +02:00
if type(line) in [Continue,Enddo]:
2009-09-03 17:44:00 +02:00
buffer = line.text.split()
if buffer[0] == number:
2009-09-04 15:11:42 +02:00
text[i] = Enddo(line.i," enddo",line.filename)
2009-09-03 17:44:00 +02:00
return
error.fail(text[begin],"Old-style do loops should end with 'continue' or 'end do'")
2013-07-01 13:12:37 +02:00
2009-09-03 17:44:00 +02:00
result = []
for i in range(len(text)):
line = text[i]
2010-10-02 23:42:55 +02:00
if type(line) == Do:
2009-09-03 17:44:00 +02:00
buffer = line.text.split()
2010-11-26 09:28:12 +01:00
try:
if buffer[1].isdigit():
2009-09-03 17:44:00 +02:00
number = buffer.pop(1)
change_matching_enddo(i,number)
2009-09-04 15:11:42 +02:00
line.text = " ".join(buffer)
2010-11-26 09:28:12 +01:00
except IndexError:
pass
2009-09-03 17:44:00 +02:00
result.append(line)
return result
######################################################################
def change_single_line_ifs(text):
'''Changes:
2013-07-01 13:12:37 +02:00
if (test) result
2009-09-03 17:44:00 +02:00
to
if (test) then
result
endif'''
2010-10-02 23:42:55 +02:00
assert type(text) == list
2009-09-03 22:31:43 +02:00
result = []
for line in text:
2010-10-02 23:42:55 +02:00
if type(line) == If:
2010-05-19 19:01:05 +02:00
if line.lower.endswith("then"):
2009-09-03 22:31:43 +02:00
result.append(line)
else:
buffer = line.text
begin = buffer.find('(')
if begin < 0:
error.fail(line,"Error in if statement")
level = 0
instring = False
for i,c in enumerate(buffer[begin:]):
if c == "'":
instring = not instring
if instring:
pass
elif c == '(':
level +=1
elif c == ')':
level -= 1
if level == 0:
end = begin+i+1
break
if level != 0:
error.fail(line,"Error in if statement")
test = buffer[:end]
code = buffer[end:]
i = line.i
f = line.filename
result.append( If(i,"%s then"%(test,),f) )
result += get_type(i,f,code,False)[0]
2009-09-04 15:11:42 +02:00
result.append( Endif(i," endif",f) )
2009-09-03 22:31:43 +02:00
else:
result.append(line)
return result
2009-09-03 16:52:38 +02:00
######################################################################
2009-09-03 17:44:00 +02:00
def check_begin_end(text):
2009-09-03 16:52:38 +02:00
'''Checks x...endx consistence'''
2009-09-05 15:37:23 +02:00
filter_line = lambda line: type(line) in [ Do, Enddo, If, Endif, \
Program, Begin_provider, End_provider, \
2009-09-05 15:37:23 +02:00
Subroutine, Function, End, Begin_doc, End_doc ]
2020-01-27 18:22:35 +01:00
text = list(filter(filter_line, text))
2009-09-03 16:52:38 +02:00
2009-09-03 23:12:32 +02:00
d = { 'do' : Do, 'enddo': Enddo,
'if' : If, 'endif': Endif,
'_doc': Begin_doc, 'end_doc': End_doc}
2010-10-02 23:42:55 +02:00
assert type(text) == list
2009-09-03 16:52:38 +02:00
def find_matching_end_ifdo(begin,x):
level = 1
for i in range(begin+1,len(text)):
line = text[i]
2010-10-02 23:42:55 +02:00
if type(line) == d[x]:
2009-09-03 16:52:38 +02:00
level += 1
2010-10-02 23:42:55 +02:00
elif type(line) == d["end%s"%(x,)]:
2009-09-03 16:52:38 +02:00
level -= 1
if level == 0:
return True
2009-09-05 15:37:23 +02:00
elif type(line) in [End, End_provider]:
2009-09-03 16:52:38 +02:00
break
2009-09-03 23:12:32 +02:00
error.fail(text[begin],"Missing 'end%s'"%(x,))
2009-09-03 16:52:38 +02:00
def find_matching_end_subfunpro(begin,x):
2014-01-07 17:01:40 +01:00
line = text[begin]
2009-09-03 16:52:38 +02:00
for i in range(begin+1,len(text)):
line = text[i]
2010-10-02 23:42:55 +02:00
if type(line) == x:
2009-09-03 16:52:38 +02:00
return
if type(line) in [ Subroutine, Function, Program, Begin_provider ]:
error.fail(text[begin],type(line).str+" is not closed")
error.fail(text[begin],type(line).str + " is not closed")
2009-09-03 16:52:38 +02:00
2013-07-01 13:12:37 +02:00
2009-09-03 16:52:38 +02:00
level = 0
2009-09-03 23:12:32 +02:00
for i,line in enumerate(text):
2010-10-02 23:42:55 +02:00
if type(line) == Begin_doc:
2009-09-03 23:12:32 +02:00
find_matching_end_ifdo(i,'_doc')
2009-09-03 16:52:38 +02:00
for i,line in enumerate(text):
2010-10-02 23:42:55 +02:00
if type(line) == Do:
2009-09-03 16:52:38 +02:00
find_matching_end_ifdo(i,'do')
2010-10-02 23:42:55 +02:00
elif type(line) == If:
2009-09-03 16:52:38 +02:00
find_matching_end_ifdo(i,'if')
elif type(line) in [Subroutine, Function, Program]:
2009-09-03 16:52:38 +02:00
level += 1
find_matching_end_subfunpro(i,End)
2010-10-02 23:42:55 +02:00
elif type(line) == Begin_provider:
2009-09-03 16:52:38 +02:00
level += 1
find_matching_end_subfunpro(i,End_provider)
2010-10-02 23:42:55 +02:00
elif type(line) == End:
2009-09-03 16:52:38 +02:00
level -= 1
2010-10-02 23:42:55 +02:00
elif type(line) == End_provider:
2009-09-03 16:52:38 +02:00
level -= 1
if level < 0:
error.fail(line,"Beginning of block not matched")
return True
2009-09-03 17:44:00 +02:00
######################################################################
def remove_ifdefs(text):
2010-10-02 23:42:55 +02:00
assert type(text) == list
2009-09-03 23:12:32 +02:00
result = []
do_print = True
for line in text:
2010-10-02 23:42:55 +02:00
if type(line) == Irp_If:
2009-09-03 23:12:32 +02:00
var = line.text.split()[1]
do_print = var in command_line.defined
2010-10-02 23:42:55 +02:00
elif type(line) == Irp_Else:
2009-09-03 23:12:32 +02:00
do_print = not do_print
2010-10-02 23:42:55 +02:00
elif type(line) == Irp_Endif:
2009-09-03 23:12:32 +02:00
do_print = True
else:
if do_print:
result.append(line)
return result
2009-09-03 17:44:00 +02:00
######################################################################
def check_OpenMP(text):
assert type(text) == list
result = []
inside_openmp = False
for line in text:
if type(line) == Openmp:
# Detect OpenMP blocks
buffer = line.text.lower().split()
if buffer[1] == "parallel":
inside_openmp = True
if buffer[1] == "end" and buffer[2] == "parallel":
inside_openmp = False
result.append(line)
if inside_openmp:
if type(line) in [ Provide_all, Provide, Touch, SoftTouch ]:
error.fail(line,type(line).str+" is not allowed in an OpenMP block.")
return result
2009-09-02 20:45:53 +02:00
######################################################################
2009-09-04 15:11:42 +02:00
def create_preprocessed_text(filename):
2009-09-02 20:45:53 +02:00
file = open(filename,"r")
lines = file.readlines()
file.close()
result = get_text(lines,filename)
2009-12-09 20:26:09 +01:00
result = execute_templates(result)
2009-09-02 20:45:53 +02:00
result = execute_shell(result)
fortran_form = form(result)
2009-09-03 17:44:00 +02:00
result = remove_ifdefs(result)
2009-09-02 20:45:53 +02:00
result = remove_comments(result,fortran_form)
result = remove_continuation(result,fortran_form)
2009-12-09 16:48:48 +01:00
result = add_operators(result)
result = change_includes(result)
2009-09-03 17:44:00 +02:00
result = change_single_line_ifs(result)
2009-09-03 16:52:38 +02:00
result = process_old_style_do(result)
2009-09-03 17:44:00 +02:00
result = irp_simple_statements(result)
result = check_OpenMP(result)
check_begin_end(result)
2009-09-02 20:45:53 +02:00
return result
2009-09-04 15:11:42 +02:00
######################################################################
preprocessed_text = parallel_loop( lambda x,y: create_preprocessed_text(x), \
2020-01-27 18:22:35 +01:00
[(x,None) for x in irpf90_files] )
2009-09-04 15:11:42 +02:00
######################################################################
def debug():
for filename, txt in preprocessed_text:
2012-12-19 11:35:21 +01:00
if filename == 'invert.irp.f':
2020-01-27 18:22:35 +01:00
print("=== "+filename+" ===")
2009-09-04 15:11:42 +02:00
for line in txt:
2020-01-27 18:22:35 +01:00
print(line)
print(irpf90_files)
2009-09-04 15:11:42 +02:00
2013-07-01 13:12:37 +02:00
if __name__ == '__main__':
2009-09-04 15:11:42 +02:00
debug()
2009-09-02 20:45:53 +02:00