10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-11-19 12:32:22 +01:00
irpf90/src/parsed_text.py

458 lines
14 KiB
Python
Raw Normal View History

2009-09-05 00:18:45 +02:00
#!/usr/bin/python
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.
# Copyright (C) 2009 Anthony SCEMAMA
#
# 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
# 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
from util import *
from irpf90_t import *
from variables import variables
from preprocessed_text import preprocessed_text
from subroutines import subroutines
import regexps
2009-09-05 15:37:23 +02:00
import error
2009-09-05 00:18:45 +02:00
2009-10-21 17:24:24 +02:00
vtuple = map(lambda v: (v, variables[v].same_as, variables[v].regexp), variables.keys())
stuple = map(lambda s: (s, subroutines[s].regexp), subroutines.keys())
stuple = filter(lambda s: subroutines[s[0]].is_function, stuple)
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.text.lower()
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)
sub_done = True
if regexp.search(buffer) is not None:
result.append(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 = []
sub_done = False
buffer = line.text.lower()
for s,regexp in stuple:
if s in buffer:
if regexp.search(buffer) is not None:
result.append(s)
return result
2009-09-05 15:37:23 +02:00
def find_subroutine_in_line(line):
assert isinstance(line,Call)
2009-09-05 16:05:00 +02:00
buffer = line.text.split('(')[0]
buffer = buffer.split()[1]
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
2009-09-05 16:05:00 +02:00
all_others = make_single(flatten( map(fun,main_vars) ))
2009-09-05 15:37:23 +02:00
all_others.sort()
if len(all_others) == len(vars):
2009-09-05 16:05:00 +02:00
vars.sort()
2009-09-05 15:37:23 +02:00
for x,y in zip(vars,all_others):
if x != y:
message = "The following entities should be touched:\n"
message = "\n".join([message]+map(lambda x: "- %s"%(x,),all_others))
error.fail(line,message)
2009-09-05 00:18:45 +02:00
def get_parsed_text():
2009-09-05 16:05:00 +02:00
main_result = []
2009-09-07 16:35:34 +02:00
varlist = []
2009-09-05 00:18:45 +02:00
for filename, text in preprocessed_text:
2009-09-05 16:05:00 +02:00
result = []
2009-09-05 00:18:45 +02:00
for line in filter(
lambda x: type(x) not in [ Doc, Begin_doc, End_doc ],
text):
if type(line) in [ \
Empty_line,
Continue,
Return,
Begin_shell,
End_shell,
Openmp,
Use,
Enddo,
End_select,
Endif,
Implicit,
Program,
Subroutine,
Function,
End,
]:
2009-09-05 16:05:00 +02:00
result.append( ([],line) )
2009-09-07 16:35:34 +02:00
elif isinstance(line,End_provider):
varlist = []
result.append( ([],line) )
2009-09-05 00:18:45 +02:00
elif isinstance(line,Provide):
2009-09-07 16:35:34 +02:00
l = line.text.lower().split()[1:]
l = filter(lambda x: x not in varlist, l)
2009-09-09 16:59:43 +02:00
for v in l:
if v not in variables.keys():
error.fail(line,"Variable %s is unknown"%(v))
2009-09-05 16:05:00 +02:00
result.append( (l,Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2009-09-05 15:37:23 +02:00
elif isinstance(line,Call):
l = find_variables_in_line(line)
l = filter(lambda x: x not in varlist, l)
2009-09-05 15:37:23 +02:00
sub = find_subroutine_in_line(line)
2009-09-05 16:05:00 +02:00
if sub not in subroutines:
2009-09-05 15:37:23 +02:00
t = Simple_line
result.append( (l,Simple_line(line.i,line.text,line.filename)) )
2009-09-05 15:37:23 +02:00
else:
result.append( (l,line) )
if subroutines[sub].touches != []:
result.append( ([],Provide_all(line.i,"",line.filename)) )
2009-09-05 15:37:23 +02:00
elif isinstance(line,Free):
vars = line.text.split()
if len(vars) < 2:
error.fail(line,"Syntax error")
2009-09-08 18:20:20 +02:00
vars = map(lower,vars[1:])
for v in vars:
variables[v].is_freed = True
2009-09-05 15:37:23 +02:00
result.append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2009-09-09 16:59:43 +02:00
use = map(lambda x: " use %s"%(variables[x].fmodule),vars)
2009-09-05 15:37:23 +02:00
for var in vars:
2009-09-09 16:59:43 +02:00
result += map(lambda x: ([],Use(line.i,x,line.filename)),
make_single(use))
result += map(lambda x: ([],Simple_line(line.i,x,line.filename)),
variables[var].free)
2009-09-08 18:20:20 +02:00
elif isinstance(line,Irp_read):
variables[line.filename]._is_read = True
2009-09-08 18:20:20 +02:00
result.append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
elif isinstance(line,Irp_write):
variables[line.filename]._is_written = True
2009-09-08 18:20:20 +02:00
result.append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) )
2009-09-05 15:37:23 +02:00
elif isinstance(line,Touch):
vars = line.text.split()
if len(vars) < 2:
error.fail(line,"Syntax error")
2009-09-05 16:05:00 +02:00
vars = map(lower,vars[1:])
2009-09-08 18:20:20 +02:00
for v in vars:
2009-09-16 15:59:13 +02:00
if v not in variables:
error.fail(line,"Variable %s unknown"%(v,))
2009-09-09 16:59:43 +02:00
variables[v]._is_touched = True
2009-09-05 15:37:23 +02:00
def fun(x):
main = variables[x].same_as
return main
main_vars = make_single( 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)
2009-09-16 15:59:13 +02:00
result += [ (vars,Simple_line(line.i,"!",line.filename)),
([],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)) ]
2009-09-05 16:05:00 +02:00
result += flatten(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))
result += map( fun, main_vars[:-1] )
2009-09-05 15:37:23 +02:00
result += [ ([],Provide_all(line.i,"! <<< END TOUCH",line.filename)) ]
2009-09-06 00:47:20 +02:00
elif type(line) in [ Begin_provider, Cont_provider ]:
2009-09-07 16:35:34 +02:00
if isinstance(line,Begin_provider):
varlist = []
2009-09-06 00:47:20 +02:00
buffer = map(strip,line.text.replace(']','').split(','))
assert len(buffer) > 1
v = buffer[1].lower()
2009-09-07 16:35:34 +02:00
varlist.append(v)
2009-09-06 00:47:20 +02:00
variable_list = find_variables_in_line(line)
2009-12-14 13:36:31 +01:00
try:
variable_list.remove(variables[v].same_as)
except ValueError:
print v, variables[v].same_as
raise
2009-09-06 00:47:20 +02:00
result.append( (variable_list,line) )
2009-09-05 00:18:45 +02:00
else:
l = find_variables_in_line(line)
2009-09-07 16:35:34 +02:00
l = filter(lambda x: x not in varlist, l)
2009-09-05 16:05:00 +02:00
result.append( (l,line) )
main_result.append( (filename, result) )
return main_result
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):
assert isinstance(text,list)
assert t in [ Declaration, Implicit, Use, Cont_provider ]
inside = False
for i in range(len(text)):
vars, line = text[i]
if type(line) in [ Begin_provider, Subroutine, Function ]:
begin = i
inside = True
elif type(line) in [ End_provider, End ]:
inside = False
elif isinstance(line,t):
if inside:
text.pop(i)
begin += 1
text.insert(begin,(vars,line))
return text
result = []
for filename,text in parsed_text:
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
2009-09-07 16:35:34 +02:00
######################################################################
def move_variables():
main_result = []
for filename, text in parsed_text:
result = []
# 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()
for vars,line in revtext:
if type(line) in [ End_provider,End ]:
varlist = []
result.append( ([],line) )
elif type(line) in [ Endif, End_select ]:
2009-11-02 16:16:13 +01:00
old_ifvars.append( list(ifvars) )
old_elsevars.append( list(elsevars) )
old_varlist.append( list(varlist) )
2009-09-07 16:35:34 +02:00
varlist = []
result.append( ([],line) )
2009-09-07 16:55:11 +02:00
elif type(line) == Else:
2009-11-02 16:16:13 +01:00
elsevars += list(varlist)
2009-09-07 16:55:11 +02:00
result.append( (varlist,line) )
varlist = []
elif type(line) in [ Elseif, Case ]:
2009-11-02 16:16:13 +01:00
ifvars += list(varlist)
2009-09-07 16:35:34 +02:00
result.append( (varlist,line) )
if vars != []:
varlist = old_varlist.pop()
varlist += vars
2009-11-02 16:16:13 +01:00
old_varlist.append( list(varlist) )
2009-09-07 16:35:34 +02:00
varlist = []
elif type(line) in [ If, Select ]:
2009-11-02 16:16:13 +01:00
ifvars += list(varlist)
2009-09-07 16:35:34 +02:00
result.append( (varlist,line) )
2009-09-07 16:55:11 +02:00
vars += filter(lambda x: x in elsevars, ifvars)
ifvars = old_ifvars.pop()
elsevars = old_elsevars.pop()
2009-11-02 16:16:13 +01:00
varlist = old_varlist.pop() + vars
2009-09-07 16:35:34 +02:00
elif type(line) in [ Begin_provider, Subroutine, Function ]:
varlist += vars
result.append( (varlist,line) )
if old_varlist != [] \
or old_ifvars != [] \
or old_elsevars != []:
error.fail(line,"End if missing")
2009-09-07 16:35:34 +02:00
varlist = []
2009-09-16 15:59:13 +02:00
elif isinstance(line,Provide_all):
result.append( (vars,line) )
2009-09-07 16:35:34 +02:00
else:
varlist += vars
result.append( ([],line) )
result.reverse()
2009-11-02 16:16:13 +01:00
2009-09-07 16:35:34 +02:00
# 2nd pass
text = result
result = []
old_varlist = []
varlist = []
for vars,line in text:
if vars != []:
vars = make_single(vars)
if type(line) in [ Begin_provider, Subroutine, Function ]:
varlist = list(vars)
elif type(line) in [ If, Select ]:
old_varlist.append(varlist)
vars = filter(lambda x: x not in varlist,vars)
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)
vars = filter(lambda x: x not in varlist,vars)
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:
2009-09-29 14:51:33 +02:00
vars += varlist
2009-09-07 16:35:34 +02:00
elif type(line) in [ End_provider, End ]:
assert old_varlist == []
varlist = []
result.append( (vars,line) )
main_result.append( (filename, result) )
return main_result
parsed_text = move_variables()
2009-10-21 17:24:24 +02:00
######################################################################
def build_sub_needs():
# Needs
for filename, text in parsed_text:
sub = None
for vars,line in text:
if type(line) in [ Subroutine, Function ]:
subname = find_subname(line)
sub = subroutines[subname]
sub.needs = []
2009-10-21 23:44:09 +02:00
sub.to_provide = vars
2009-10-21 17:24:24 +02:00
elif isinstance(line,End):
sub.needs = make_single(sub.needs)
sub = None
if sub is not None:
sub.needs += vars
build_sub_needs()
#####################################################################
def add_subroutine_needs():
main_result = []
for filename, text in parsed_text:
result = []
for vars,line in text:
if isinstance(line,Call):
subname = find_subname(line)
2009-10-21 23:44:09 +02:00
vars = subroutines[subname].to_provide
2009-10-21 17:24:24 +02:00
result.append( (vars,line) )
main_result.append( (filename, result) )
return main_result
parsed_text = add_subroutine_needs()
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:
if isinstance(line,Begin_provider):
buffer = map(strip,line.text.replace(']',',').split(','))
var = variables[buffer[1].lower()]
var.needs = []
var.to_provide = vars
elif isinstance(line,End_provider):
var.needs = make_single(var.needs)
var.to_provide = make_single(var.to_provide)
var = None
if var is not None:
var.needs += vars
2009-10-21 23:44:09 +02:00
if isinstance(line,Call):
subname = find_subname(line)
var.needs += subroutines[subname].needs
elif type(line) in [ \
Simple_line, Assert,
Do , If,
Elseif , Select,
]:
funcs = find_funcs_in_line(line)
for f in funcs:
var.needs += subroutines[f].needs
2009-09-07 18:02:06 +02:00
for v in variables.keys():
main = variables[v].same_as
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
for v in variables.keys():
variables[v].needed_by = []
for v in variables.keys():
main = variables[v].same_as
if main != v:
variables[v].needed_by = variables[main].needed_by
for v in variables.keys():
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)
2009-09-07 18:02:06 +02:00
for v in variables.keys():
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:
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
######################################################################
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:
if not isinstance(line,Provide_all):
if do_level > 0 and vars != []:
print "Optimization: %s line %d"%(line.filename,line.i)
for v in vars:
print " PROVIDE ",v
if isinstance(line,Do):
do_level += 1
elif isinstance(line,Enddo):
do_level -= 1
check_opt()
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)):
2010-02-19 11:41:57 +01:00
if parsed_text[i][0] == 'intmul.irp.f':
2009-09-07 16:35:34 +02:00
print '!-------- %s -----------'%(parsed_text[i][0])
for line in parsed_text[i][1]:
print line[1]
2009-09-09 16:59:43 +02:00
print line[0], line[1].filename
2009-09-07 18:02:06 +02:00