10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-06-02 11:25:19 +02:00
irpf90/src/irpy_files.py
2017-07-11 21:05:56 +02:00

324 lines
10 KiB
Python

from util import parmap, lazy_write_file
from util import flatten, listdir
from util import logger
from lib.manager import irpy
import os
import irpf90_t
import sys
from command_line import command_line
class Irpy_comm_world(object):
'''Maestro.'''
def __init__(self, l_dir=None, l_file=None):
# (Iter, Iter) -> None
# Create directories
from itertools import ifilterfalse
i_folder = ifilterfalse(os.path.exists, (irpf90_t.irpdir, irpf90_t.mandir))
map(os.mkdir, i_folder)
# List file
l_dir = l_dir if l_dir else (command_line.include_dir + ['.'])
l_not_dir = [d for d in l_dir if not (os.path.exists(d) and os.path.isdir(d))]
if l_not_dir:
logger.error('Try to include no existing directory: [%s]' % ','.join(l_not_dir))
sys.exit(1)
# Create folder in IRPDIR
i_folder = ifilterfalse(os.path.exists, (os.path.join(irpf90_t.irpdir, d) for d in l_dir))
map(os.mkdir, i_folder)
s_folder_abs = set(os.path.abspath(path) for path in l_dir)
s_file_folder_all = set(flatten(listdir(path, abspath=True) for path in s_folder_abs))
# Take everything!
s_file_folder = filter(lambda f: os.path.isfile(f) and not f.startswith("."),
s_file_folder_all)
s_file_tot = set(l_file) if l_file else set()
s_file_tot.update(s_file_folder)
s_file_rel = set(os.path.relpath(f, self.cwd) for f in s_file_tot)
# Lazy Copy file
for f in s_file_rel:
src = os.path.join(self.cwd, f)
text_ref = open(src, 'rb').read()
dest = os.path.join(self.cwd, irpf90_t.irpdir, f)
lazy_write_file(dest, text_ref)
if command_line.do_codelet:
s_file_tot.update(command_line.codelet[3])
# No filter the irpf90 file
self.irpf90_files_ordered = sorted(filter(lambda f: f.endswith(".irp.f"), s_file_rel))
@irpy.lazy_property
def cwd(self):
return os.getcwd()
@irpy.lazy_property
def t_filename_preprocessed_text(self):
'''Tuple (filename, preprocessed_text)'''
from preprocessed_text import Preprocess_text
def worker_preprocess(filename):
return (filename, Preprocess_text(filename).preprocessed_text)
return parmap(worker_preprocess, self.irpf90_files_ordered)
@irpy.lazy_property
def l_preprocessed_text(self):
# (None) -> List[Line]
'''List preprocessed_text'''
return [line for _, text in self.t_filename_preprocessed_text for line in text]
@irpy.lazy_property
def d_type_lines(self):
from collections import defaultdict
d = defaultdict(list)
for i, line in enumerate(self.l_preprocessed_text):
d[type(line)] += [(i, line)]
return d
@irpy.lazy_property
def d_entity(self):
# None -> Dict[Str,Entity]
'''And entity is a collection of line between BEGIN_PROVIDER and END_PROVIDER '''
from irpf90_t import Begin_provider, End_provider
from entity import Entity
l_begin = [i for i, line in self.d_type_lines[Begin_provider]]
l_end = [i for i, line in self.d_type_lines[End_provider]]
l_provider = [self.l_preprocessed_text[begin:end] for begin, end in zip(l_begin, l_end)]
l_ent = []
for icount, buf in enumerate(l_provider):
from functools import partial
Ent_part = partial(Entity, buf, icount, comm_world=self)
ent = Ent_part()
l_ent += [ent] + [Ent_part(name) for name in ent.l_others_name]
# O(2) but who care
l_duplicate = [x for x in l_ent if l_ent.count(x) > 1]
if l_duplicate:
from util import logger
logger.error('You have duplicate PROVIDER: %s' %
' '.join([e.name for e in l_duplicate]))
import sys
sys.exit(1)
# Python 2.6 Don't allow list comprehesion
d_ent = dict()
for e in l_ent:
d_ent[e.name] = e
#
# Second pass
# Modify parameter of variables
# Touch Softouch
def find_variable(line):
from util import logger
import sys
l_var = line.lower.split()[1:]
if len(l_var) < 1:
logger.error("Syntax error: %s", line)
import sys
sys.exit(1)
try:
e = next(v for v in l_var if v not in d_ent)
except StopIteration:
pass
else:
logger.error("Entity %s unknown: %s" % (e, line))
import sys
sys.exit(1)
return l_var
d_modif = dict()
from irpf90_t import Touch, SoftTouch, Free
from util import flatten
for cmd, l_type in [('is_self_touched', [Touch, SoftTouch]), ('is_free', [Free])]:
l_line = flatten([self.d_type_lines[type_] for type_ in l_type])
l_name = flatten([find_variable(line) for _, line in l_line])
d_modif[cmd] = l_name
# Read and Write
from irpf90_t import Irp_read, Irp_write
for cmd, type_ in [('is_read', Irp_read), ('is_written', Irp_write)]:
l_name = [line.filename for _, line in self.d_type_lines[type_]]
d_modif[cmd] = l_name
#Do the modifcation
for cmd, l_name in d_modif.items():
for name in l_name:
setattr(d_ent[name], cmd, True)
return d_ent
@irpy.lazy_property_mutable
def d_routine(self):
'''
Dictionnary name -> Routine object.
Routine is a collection of line between Subroutine / Function
'''
# ~#~#~#~#~#
# Create the dict
# ~#~#~#~#~#
from irpf90_t import Subroutine, Function, Program, End
d_type = self.d_type_lines
l_begin = sorted(i for type_ in (Subroutine, Function, Program) for i, _ in d_type[type_])
l_end = [i for i, _ in d_type[End]]
from routine import Routine
text = self.l_preprocessed_text
l_rou = [
Routine(text[b:e]) for b, e in zip(l_begin, l_end) if not isinstance(text[b], Program)
]
# Now we can create a dict and at it
d_rou = dict()
for s in l_rou:
d_rou[s.name] = s
# ~#~#~#~#~#
# Finish the initialization of the routine
# ~#~#~#~#~#
from collections import defaultdict
d_called_by = defaultdict(set)
for entity in self.d_entity.values():
name = entity.name
if entity.same_as == name:
for x in entity.calls:
d_called_by[x].add(name)
from util import uniquify
for routine in d_rou.values():
for x in routine.calls:
d_called_by[x].add(routine.name)
for routine in d_rou.values():
routine.called_by = sorted(d_called_by[routine.name])
l_set = [d_rou[name].touches_my_self for name in routine.calls if name in d_rou]
routine.touches_ancestor = set().union(*l_set)
return d_rou
@irpy.lazy_property
def t_filename_parsed_text(self):
'''(filename,parsed_text)'''
d_entity = self.d_entity
d_routine = self.d_routine
import parsed_text
vtuple = [(v, s.same_as, s.regexp) for v, s in d_entity.iteritems()]
def worker_parsed(filename_text):
filename, text = filename_text
return parsed_text.get_parsed_text(filename, text, d_entity, d_routine, vtuple)
parsed_text_0 = parmap(worker_parsed, self.t_filename_preprocessed_text)
from irpf90_t import NoDep, Declaration, Implicit, Use, Cont_provider
def moved_to_top_l(ptext):
l = [NoDep, Declaration, Implicit, Use, Cont_provider]
for _, text in ptext:
parsed_text.move_to_top_list(text, l)
#Touch routine
parsed_text.build_sub_needs(parsed_text_0, d_routine)
moved_to_top_l(parsed_text_0)
parsed_text_1 = parsed_text.add_subroutine_needs(parsed_text_0, d_routine)
parsed_text_1 = parsed_text.move_variables(parsed_text_1)
moved_to_top_l(parsed_text_1)
parsed_text.check_opt(parsed_text_1)
parsed_text_1 = parsed_text.perform_loop_substitutions(parsed_text_1)
#touch entity
stuple = [(s, v.regexp) for s, v in d_routine.iteritems() if v.is_function]
parsed_text.build_needs(parsed_text_1, d_routine, stuple, d_entity)
return parsed_text_1
@irpy.lazy_property
def d_module(self):
from module import Fmodule
result = dict()
for filename, text in self.t_filename_parsed_text:
result[filename] = Fmodule(text, filename, self.d_entity)
return result
def write_modules(self):
from irpf90_t import irpdir
from util import lazy_write_file
import os
for m in self.d_module.values():
# Module data
if m.has_irp_module:
filename = os.path.join(irpdir, '%s.irp.module.F90' % m.filename)
text = '\n'.join(m.head)
lazy_write_file(filename, '%s\n' % text)
# Subroutines
filename = os.path.join(irpdir, '%s.irp.F90' % m.filename)
text = '\n'.join(m.header + m.generated_text + m.residual_text)
lazy_write_file(filename, '%s\n' % text)
def create_stack(self):
from util import lazy_write_file
from util import ashes_env
str_ = ashes_env.render('irp_stack.f90', {
'do_debug': command_line.do_debug,
'do_openmp': command_line.do_openmp,
'do_memory': command_line.do_memory
})
filename = os.path.join(irpf90_t.irpdir, 'irp_stack.irp.F90')
lazy_write_file(filename, str_)
def create_buildfile(self, ninja):
import build_file
build_file.run(self.d_module, ninja)
def create_touches(self):
import touches
touches.create(self.d_module, self.d_entity)
def create_man(self):
import create_man as c_man
c_man.run(self.d_entity, self.d_routine)
def create_lock(self):
from util import lazy_write_file
from util import ashes_env
str_ = ashes_env.render('irp_lock.f90', {'entity': sorted(self.d_entity)})
filename = os.path.join(irpf90_t.irpdir, 'irp_locks.irp.F90')
lazy_write_file(filename, str_)