10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-11-10 16:13:42 +01:00
irpf90/src/parsed_text.py

548 lines
17 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-09 19:53:05 +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-09 19:53:05 +02:00
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
2009-09-23 12:51:27 +02:00
2009-09-05 00:18:45 +02:00
2020-01-27 18:22:35 +01:00
from .util import *
from .irpf90_t import *
from .variables import variables
from .preprocessed_text import preprocessed_text
from .subroutines import subroutines
import regexps, re
2020-01-27 18:22:35 +01:00
from . import error
2009-09-05 00:18:45 +02:00
2020-01-27 18:22:35 +01:00
vtuple = [(v, variables[v].same_as, variables[v].regexp) for v in list(variables.keys())]
stuple = [(s, subroutines[s].regexp) for s in list(subroutines.keys())]
stuple = [s for s in stuple if subroutines[s[0]].is_function]
re_string_sub = regexps.re_string.sub
regexps_re_string_sub = regexps.re_string.sub
2009-09-05 00:18:45 +02:00
def find_variables_in_line(line):
assert isinstance(line,Line)
result = []
2009-09-17 11:56:04 +02:00
sub_done = False
buffer = line.lower
2010-05-19 19:01:05 +02:00
ap = result.append
2009-10-21 17:24:24 +02:00
for v,same_as,regexp in vtuple:
if v in buffer:
2009-09-17 11:56:04 +02:00
if not sub_done:
buffer = regexps_re_string_sub('',buffer)
2009-09-17 11:56:04 +02:00
sub_done = True
if regexp.search(buffer) is not None:
2010-05-19 19:01:05 +02:00
ap(same_as)
2009-09-05 00:18:45 +02:00
return result
2009-10-21 17:24:24 +02:00
def find_funcs_in_line(line):
assert isinstance(line,Line)
result = []
append = result.append
2009-10-21 17:24:24 +02:00
sub_done = False
buffer = line.lower
2009-10-21 17:24:24 +02:00
for s,regexp in stuple:
if s in buffer:
if regexp.search(buffer) is not None:
append(s)
2009-10-21 17:24:24 +02:00
return result
2009-09-05 15:37:23 +02:00
def find_subroutine_in_line(line):
2010-10-02 23:42:55 +02:00
assert type(line) == Call
2009-09-05 16:05:00 +02:00
buffer = line.text.split('(')[0]
buffer = buffer.split()[1].lower()
2009-09-05 16:05:00 +02:00
return buffer
2009-09-05 15:37:23 +02:00
2009-09-05 16:05:00 +02:00
def check_touch(line,vars,main_vars):
2009-09-05 15:37:23 +02:00
def fun(main_var):
if main_var not in variables:
error.fail(line,"Variable %s unknown"%(main_var,))
x = variables[main_var]
return [main_var]+x.others
2020-01-27 18:22:35 +01:00
all_others = make_single(flatten( list(map(fun,main_vars)) ))
2009-09-05 15:37:23 +02:00
all_others.sort()
2013-07-09 18:06:16 +02:00
vars.sort()
for x,y in zip(vars,all_others):
2009-09-05 15:37:23 +02:00
if x != y:
message = "The following entities should be touched:\n"
2020-01-27 18:22:35 +01:00
message = "\n".join([message]+["- %s"%(x,) for x in all_others])
2009-09-05 15:37:23 +02:00
error.fail(line,message)
2009-09-05 00:18:45 +02:00
2010-10-02 23:04:30 +02:00
################################################################################
def update_variables():
for filename,text in preprocessed_text:
2020-01-27 18:22:35 +01:00
for line in [x for x in text if type(x) in [ Touch, SoftTouch ]]:
vars = line.lower.split()
2010-10-02 23:04:30 +02:00
if len(vars) < 2:
error.fail(line,"Syntax error")
for v in vars[1:]:
if v not in variables:
error.fail(line,"Variable %s unknown"%(v,))
variables[v]._is_touched = True
2020-01-27 18:22:35 +01:00
for line in [x for x in text if type(x) == Free]:
vars = line.lower.split()
2010-10-02 23:04:30 +02:00
if len(vars) < 2:
error.fail(line,"Syntax error")
for v in vars[1:]:
if v not in variables:
error.fail(line,"Variable %s unknown"%(v,))
variables[v].is_freed = True
2020-01-27 18:22:35 +01:00
for line in [x for x in text if type(x) == Irp_read]:
2010-10-02 23:04:30 +02:00
variables[line.filename]._is_read = True
2020-01-27 18:22:35 +01:00
for line in [x for x in text if type (x) == Irp_write]:
2010-10-02 23:04:30 +02:00
variables[line.filename]._is_written = True
################################################################################
2013-07-09 19:53:05 +02:00
2009-09-05 00:18:45 +02:00
def get_parsed_text():
def func(filename, text):
varlist = []
2009-09-05 16:05:00 +02:00
result = []
append = result.append
2010-10-02 23:42:55 +02:00
for line in text: #filter(
# lambda x: type(x) not in [ Doc, Begin_doc, End_doc ],
# text):
2009-09-05 00:18:45 +02:00
if type(line) in [ \
Empty_line,
Continue,
Return,
Begin_shell,
End_shell,
Openmp,
Directive,
2009-09-05 00:18:45 +02:00
Use,
Enddo,
End_select,
Endif,
Implicit,
Program,
Subroutine,
Function,
End,
2013-07-09 19:53:05 +02:00
]:
append( ([],line) )
2010-10-02 23:42:55 +02:00
elif type(line) in [ Begin_provider, Cont_provider ]:
if type(line) == Begin_provider:
varlist = []
2020-01-27 18:22:35 +01:00
buffer = list(map(strip,line.lower.replace(']','').split(',')))
2010-10-02 23:42:55 +02:00
assert len(buffer) > 1
v = buffer[1]
varlist.append(v)
variable_list = find_variables_in_line(line)
try:
variable_list.remove(variables[v].same_as)
except ValueError:
2020-01-27 18:22:35 +01:00
print(v, variables[v].same_as)
2010-10-02 23:42:55 +02:00
raise
append( (variable_list,line) )
elif type(line) == End_provider:
2009-09-07 16:35:34 +02:00
varlist = []
append( ([],line) )
2010-10-02 23:42:55 +02:00
elif type(line) == Provide:
l = line.lower.split()[1:]
2020-01-27 18:22:35 +01:00
l = [x for x in l if x not in varlist]
2009-09-09 16:59:43 +02:00
for v in l:
2011-04-09 23:45:50 +02:00
if v not in variables:
2009-09-09 16:59:43 +02:00
error.fail(line,"Variable %s is unknown"%(v))
append( (l,Provide(line.i,"",line.filename)) )
append( (l,Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2011-03-03 15:46:21 +01:00
elif type(line) == NoDep:
l = line.lower.split()[1:]
for v in l:
2011-04-09 23:45:50 +02:00
if v not in variables:
2011-03-03 15:46:21 +01:00
error.fail(line,"Variable %s is unknown"%(v))
2020-01-27 18:22:35 +01:00
l = ["-%s"%(x) for x in l]
2011-03-03 15:46:21 +01:00
append( (l,Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2010-10-02 23:42:55 +02:00
elif type(line) in [ Touch, SoftTouch ]:
vars = line.lower.split()
2009-09-05 15:37:23 +02:00
if len(vars) < 2:
error.fail(line,"Syntax error")
vars = vars[1:]
2009-09-05 15:37:23 +02:00
def fun(x):
main = variables[x].same_as
return main
2020-01-27 18:22:35 +01:00
main_vars = make_single( list(map(fun, vars)) )
2009-09-05 16:05:00 +02:00
check_touch(line,vars,main_vars)
2009-09-05 15:37:23 +02:00
txt = " ".join(vars)
2010-10-02 23:04:30 +02:00
append ( (vars,Simple_line(line.i,"!",line.filename)) )
append ( ([],Simple_line(line.i,"! >>> TOUCH %s"%(txt,),line.filename)) )
2009-09-05 15:37:23 +02:00
def fun(x):
if x not in variables:
error.fail(line,"Variable %s unknown"%(x,))
return [ ([],Simple_line(line.i," call touch_%s"%(x,),line.filename)),
2009-09-09 16:59:43 +02:00
([],Use(line.i," use %s"%(variables[x].fmodule), line.filename)) ]
2020-01-27 18:22:35 +01:00
result += flatten(list(map( fun, main_vars )))
2009-09-05 15:37:23 +02:00
def fun(x):
if x not in variables:
error.fail(line,"Variable %s unknown"%(x,))
2009-09-05 16:05:00 +02:00
return ([],Simple_line(line.i," %s_is_built = .True."%(x,),line.filename))
2020-01-27 18:22:35 +01:00
result += list(map( fun, main_vars[:-1] ))
2010-10-02 23:42:55 +02:00
if type(line) == SoftTouch:
2010-10-02 23:04:30 +02:00
append ( ([],Simple_line(line.i,"! <<< END TOUCH (Soft)",line.filename)) )
2010-03-29 20:43:00 +02:00
else:
2010-10-02 23:04:30 +02:00
append ( ([],Provide_all(line.i,"! <<< END TOUCH",line.filename)) )
2010-10-02 23:42:55 +02:00
elif type(line) == Call:
l = find_variables_in_line(line)
2020-01-27 18:22:35 +01:00
l = [x for x in l if x not in varlist]
2010-10-02 23:42:55 +02:00
sub = find_subroutine_in_line(line)
if sub not in subroutines:
t = Simple_line
append( (l,Simple_line(line.i,line.text,line.filename)) )
else:
append( (l,line) )
if subroutines[sub].touches != []:
append( ([],Provide_all(line.i,"",line.filename)) )
elif type(line) == Free:
vars = line.lower.split()
2010-10-02 23:42:55 +02:00
vars = vars[1:]
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2020-01-27 18:22:35 +01:00
use = [" use %s"%(variables[x].fmodule) for x in vars]
2010-10-02 23:42:55 +02:00
for var in vars:
2020-01-27 18:22:35 +01:00
result += [([],Use(line.i,x,line.filename)) for x in make_single(use)]
result += [([],Simple_line(line.i,x,line.filename)) for x in variables[var].free]
2010-10-02 23:42:55 +02:00
elif type(line) == Irp_read:
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
elif type(line) == Irp_write:
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
elif type(line) in [ Begin_doc, End_doc, Doc ]:
pass
2009-09-05 00:18:45 +02:00
else:
l = find_variables_in_line(line)
2020-01-27 18:22:35 +01:00
l = [x for x in l if x not in varlist]
2010-10-02 23:04:30 +02:00
append( (l,line) )
return result
2010-10-02 23:05:38 +02:00
#main_result = []
#for filename,text in preprocessed_text:
# main_result.append( (filename, func(filename,text)) )
#return main_result
return parallel_loop(func,preprocessed_text)
2013-07-09 19:53:05 +02:00
2010-10-02 23:04:30 +02:00
update_variables()
2009-09-05 00:18:45 +02:00
parsed_text = get_parsed_text()
2009-10-21 17:24:24 +02:00
######################################################################
2009-10-21 17:24:24 +02:00
def move_to_top(text,t):
2010-10-02 23:42:55 +02:00
assert type(text) == list
2011-03-03 15:46:21 +01:00
assert t in [ NoDep, Declaration, Implicit, Use, Cont_provider ]
inside = False
for i in range(len(text)):
vars, line = text[i]
if type(line) in [ Begin_provider, Program, Subroutine, Function ]:
begin = i
inside = True
elif type(line) in [ End_provider, End ]:
inside = False
2010-10-02 23:42:55 +02:00
elif type(line) == t:
if inside:
text.pop(i)
begin += 1
text.insert(begin,(vars,line))
return text
result = []
for filename,text in parsed_text:
2011-03-03 15:46:21 +01:00
text = move_to_top(text,NoDep)
text = move_to_top(text,Declaration)
text = move_to_top(text,Implicit)
text = move_to_top(text,Use)
text = move_to_top(text,Cont_provider)
result.append ( (filename,text) )
parsed_text = result
######################################################################
def build_sub_needs():
# Needs
for filename, text in parsed_text:
sub = None
in_program = False
for vars,line in text:
if type(line) in [ Subroutine, Function ]:
subname = find_subname(line)
sub = subroutines[subname]
sub._needs = []
sub._to_provide = []
elif type(line) == End:
if not in_program:
sub._needs = make_single(sub._needs)
sub._to_provide = make_single(sub._to_provide)
sub = None
elif type(line) == Program:
in_program = True
if sub is not None:
if type(line) == Declaration:
sub._to_provide += vars
2011-11-28 22:12:45 +01:00
sub._needs += vars
build_sub_needs()
#####################################################################
def add_subroutine_needs():
main_result = []
for filename, text in parsed_text:
result = []
append = result.append
for vars,line in text:
if type(line) == Call:
subname = find_subname(line)
vars += subroutines[subname].to_provide
append( (vars,line) )
main_result.append( (filename, result) )
return main_result
2013-07-09 19:53:05 +02:00
parsed_text = add_subroutine_needs()
2009-09-07 16:35:34 +02:00
######################################################################
def move_variables():
def func(filename, text):
2009-09-07 16:35:34 +02:00
result = []
append = result.append
2009-09-07 16:35:34 +02:00
# 1st pass
2009-09-07 16:55:11 +02:00
varlist = []
ifvars = []
elsevars = []
old_varlist = []
old_ifvars = []
old_elsevars = []
2009-09-07 16:35:34 +02:00
revtext = list(text)
revtext.reverse()
2012-10-19 14:49:41 +02:00
try:
for vars,line in revtext:
if type(line) in [ End_provider,End ]:
varlist = []
append( ([],line) )
elif type(line) in [ Endif, End_select ]:
old_ifvars.append( list(ifvars) )
old_elsevars.append( list(elsevars) )
2009-11-02 16:16:13 +01:00
old_varlist.append( list(varlist) )
2012-10-19 14:49:41 +02:00
varlist = []
append( ([],line) )
elif type(line) == Else:
elsevars += list(varlist)
append( (varlist,line) )
varlist = []
elif type(line) in [ Elseif, Case ]:
ifvars += list(varlist)
append( (varlist,line) )
if vars != []:
varlist = old_varlist.pop()
varlist += vars
old_varlist.append( list(varlist) )
varlist = []
elif type(line) in [ If, Select ]:
ifvars += list(varlist)
append( (varlist,line) )
2020-01-27 18:22:35 +01:00
vars += [x for x in ifvars if x in elsevars]
2012-10-19 14:49:41 +02:00
ifvars = old_ifvars.pop()
elsevars = old_elsevars.pop()
varlist = old_varlist.pop() + vars
elif type(line) in [ Begin_provider, Program, Subroutine, Function ]:
varlist += vars
append( (varlist,line) )
if old_varlist != [] \
or old_ifvars != [] \
or old_elsevars != []:
error.fail(line,"End if missing")
varlist = []
elif type(line) in (Provide,Provide_all):
2012-10-19 14:49:41 +02:00
append( (vars,line) )
else:
varlist += vars
append( ([],line) )
except:
error.fail(line,"Unable to parse file")
2009-09-07 16:35:34 +02:00
result.reverse()
2013-07-09 19:53:05 +02:00
2009-09-07 16:35:34 +02:00
# 2nd pass
text = result
result = []
append = result.append
2009-09-07 16:35:34 +02:00
old_varlist = []
varlist = []
2012-10-19 14:49:41 +02:00
try:
for vars,line in text:
if vars != []:
vars = make_single(vars)
if type(line) in [ Begin_provider, Program, Subroutine, Function ]:
varlist = list(vars)
elif type(line) in [ If, Select ]:
old_varlist.append(varlist)
2020-01-27 18:22:35 +01:00
vars = [x for x in vars if x not in varlist]
2012-10-19 14:49:41 +02:00
varlist = make_single(varlist + vars)
assert old_varlist is not varlist
elif type(line) in [ Elseif, Else, Case ]:
varlist = old_varlist.pop()
old_varlist.append(varlist)
2020-01-27 18:22:35 +01:00
vars = [x for x in vars if x not in varlist]
2012-10-19 14:49:41 +02:00
varlist = make_single(varlist + vars)
assert old_varlist is not varlist
elif type(line) in [ Endif, End_select ]:
varlist = old_varlist.pop()
elif type(line) == Provide_all:
vars += varlist
elif type(line) in [ End_provider, End ]:
assert old_varlist == []
varlist = []
for v in vars[:]:
if v[0] == '-':
vars.remove(v)
vars.remove(v[1:])
result.append( (vars,line) )
except:
error.fail(line,"Unable to parse file")
return result
2009-09-07 16:35:34 +02:00
main_result = []
for filename,text in parsed_text:
main_result.append( (filename, func(filename,text)) )
return main_result
#return parallel_loop(func,parsed_text)
2009-09-07 16:35:34 +02:00
parsed_text = move_variables()
2009-09-07 16:35:34 +02:00
######################################################################
def build_needs():
2009-09-07 18:02:06 +02:00
# Needs
for filename, text in parsed_text:
2009-09-09 16:59:43 +02:00
var = None
2009-09-07 18:02:06 +02:00
for vars,line in text:
2010-10-02 23:42:55 +02:00
if type(line) == Begin_provider:
2020-01-27 18:22:35 +01:00
buffer = list(map(strip,line.lower.replace(']',',').split(',')))
var = variables[buffer[1]]
2009-09-07 18:02:06 +02:00
var.needs = []
var.to_provide = vars
2010-10-02 23:42:55 +02:00
elif type(line) == End_provider:
2009-09-07 18:02:06 +02:00
var.needs = make_single(var.needs)
var.to_provide = make_single(var.to_provide)
var = None
if var is not None:
var.needs += vars
2010-10-02 23:42:55 +02:00
if type(line) == Call:
2009-10-21 23:44:09 +02:00
subname = find_subname(line)
var.needs += subroutines[subname].needs
elif type(line) in [ \
Simple_line, Assert,
Do , If,
Elseif , Select,
2013-07-09 19:53:05 +02:00
]:
funcs = find_funcs_in_line(line)
for f in funcs:
2013-07-09 19:53:05 +02:00
var.needs += subroutines[f].needs
2011-04-09 23:45:50 +02:00
for v in variables:
2013-07-09 19:53:05 +02:00
main = variables[v].same_as
2009-09-07 18:02:06 +02:00
if main != v:
variables[v].needs = variables[main].needs
variables[v].to_provide = variables[main].to_provide
2009-09-05 00:18:45 +02:00
2009-09-07 18:02:06 +02:00
# Needed_by
2011-04-09 23:45:50 +02:00
for v in variables:
2009-09-07 18:02:06 +02:00
variables[v].needed_by = []
2011-04-09 23:45:50 +02:00
for v in variables:
2013-07-09 19:53:05 +02:00
main = variables[v].same_as
2009-09-07 18:02:06 +02:00
if main != v:
variables[v].needed_by = variables[main].needed_by
2011-04-09 23:45:50 +02:00
for v in variables:
2009-09-07 18:02:06 +02:00
var = variables[v]
2009-09-09 16:59:43 +02:00
if var.is_main:
for x in var.needs:
variables[x].needed_by.append(var.same_as)
2011-04-09 23:45:50 +02:00
for v in variables:
2009-09-07 18:02:06 +02:00
var = variables[v]
var.needed_by = make_single(var.needed_by)
build_needs()
2009-09-09 16:59:43 +02:00
result = []
for filename,text in parsed_text:
2011-03-03 15:46:21 +01:00
text = move_to_top(text,NoDep)
2009-09-09 16:59:43 +02:00
text = move_to_top(text,Declaration)
text = move_to_top(text,Implicit)
text = move_to_top(text,Use)
text = move_to_top(text,Cont_provider)
result.append ( (filename,text) )
parsed_text = result
######################################################################
2020-01-27 18:22:35 +01:00
from .command_line import command_line
def check_opt():
if not command_line.do_checkopt:
return
for filename, text in parsed_text:
do_level = 0
for vars,line in text:
2010-10-02 23:42:55 +02:00
if not type(line) == Provide_all:
if do_level > 0 and vars != []:
2020-01-27 18:22:35 +01:00
print("Optimization: %s line %d"%(line.filename,line.i))
for v in vars:
2020-01-27 18:22:35 +01:00
print(" PROVIDE ",v)
2010-10-02 23:42:55 +02:00
if type(line) == Do:
do_level += 1
2010-10-02 23:42:55 +02:00
elif type(line) == Enddo:
do_level -= 1
check_opt()
######################################################################
def perform_loop_substitutions():
main_result = []
for filename, text in parsed_text:
result = []
append = result.append
for vars,line in text:
2012-12-07 15:12:10 +01:00
if type(line) in [ Do, If, Elseif ] :
2020-01-27 18:22:35 +01:00
for k,v in list(command_line.substituted.items()):
reg = v[1]
2012-05-15 18:01:27 +02:00
while reg.search(line.text) is not None:
line.text = re.sub(reg,r'\1%s\3', line.text,count=1)%v[0]
append( (vars,line) )
main_result.append( (filename, result) )
return main_result
2013-07-09 19:53:05 +02:00
parsed_text = perform_loop_substitutions()
2009-09-07 18:02:06 +02:00
######################################################################
2009-09-05 00:18:45 +02:00
if __name__ == '__main__':
2009-09-07 16:35:34 +02:00
for i in range(len(parsed_text)):
2011-11-28 22:12:45 +01:00
if parsed_text[i][0] == sys.argv[1]:
2020-01-27 18:22:35 +01:00
print('!-------- %s -----------'%(parsed_text[i][0]))
2009-09-07 16:35:34 +02:00
for line in parsed_text[i][1]:
2020-01-27 18:22:35 +01:00
print(line[1])
print(line[0], line[1].filename)
2012-11-15 12:00:43 +01:00
#for i in subroutines:
# print i, subroutines[i].needs, subroutines[i].to_provide