10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-12-22 20:33:39 +01:00

Merge pull request #18 from TApplencourt/master

IRPF90 v2
This commit is contained in:
Anthony Scemama 2017-01-26 09:40:07 +01:00 committed by GitHub
commit dd2afebb0d
36 changed files with 4071 additions and 4319 deletions

View File

@ -1,13 +1,69 @@
IRPF90 = python ../src/irpf90.py -I input -a -d IRPF90= irpf90
FC = ifort IRPF90FLAGS= -I ./ -I input/
BUILD_SYSTEM= make
.EXPORT_ALL_VARIABLES:
AR = ar
CC = gcc
CFLAGS = -O2
CXX = g++
CXXFLAGS = -O2
FC = gfortran
FCFLAGS = -O2 FCFLAGS = -O2
NINJA =
SRC=
OBJ=
LIB = LIB =
RANLIB = ranlib
include irpf90.make OBJ =
SRC =
irpf90.make: $(wildcard *.irp.f) # Dark magic below modify with caution!
$(IRPF90) # "You are Not Expected to Understand This"
# .
# /^\ .
# /\ "V",
# /__\ I O o
# //..\\ I .
# \].`[/ I
# /l\/j\ (] . O
# /. ~~ ,\/I .
# \\L__j^\/I o
# \/--v} I o .
# | | I _________
# | | I c(` ')o
# | l I \. ,/
# _/j L l\_! _//^---^\\_
ifeq ($(BUILD_SYSTEM),ninja)
BUILD_FILE=IRPF90_temp/build.ninja
IRPF90FLAGS += -j
else ifeq ($(BUILD_SYSTEM),make)
BUILD_FILE=IRPF90_temp/build.make
BUILD_SYSTEM += -j
else
DUMMY:
$(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)')
endif
define run_and_touch
$(BUILD_SYSTEM) -C $(dir $(1) ) -f $(notdir $(1) ) $(addprefix $(CURDIR)/, $(2)) && touch $(2)
endef
EXE := $(shell egrep -r '^\s*program' *.irp.f | awk '{print $$2}')
.PHONY: all
all: $(BUILD_FILE)
$(call run_and_touch, $<, $(EXE))
.NOTPARALLEL: $(EXE)
$(EXE): $(BUILD_FILE)
$(call run_and_touch, $<, $(EXE))
$(BUILD_FILE): $(shell find . -maxdepth 2 -path ./IRPF90_temp -prune -o -name '*.irp.f' -print)
$(IRPF90) $(IRPF90FLAGS)
clean:
rm -f -- $(BUILD_FILE) $(EXE) $(shell find IRPF90_temp -type f \( -name "*.o" -o -name "*.mod" -name "*.a" \) -delete;)
veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags

View File

@ -1,12 +1,8 @@
program irp_example1 program irp_example1
! integer :: x(W)
BEGIN_SHELL [ /bin/bash ] BEGIN_SHELL [ /bin/bash ]
echo print *, \'Compiled by `whoami` on `date`\' echo print *, \'Compiled by `whoami` on `date`\'
echo print *, \'$FC $FCFLAGS\' echo print *, \'$FC $FCFLAGS\'
echo print *, \'$IRPF90\' echo print *, \'$IRPF90\'
END_SHELL END_SHELL
print *, 't = ', t print *, 't = ', t
print *, 'v=', v
! print *, u2
end end

View File

@ -7,6 +7,7 @@ BEGIN_PROVIDER [integer,w]
END_PROVIDER END_PROVIDER
BEGIN_PROVIDER [ integer, v ] BEGIN_PROVIDER [ integer, v ]
implicit none
v = u2+w+2 v = u2+w+2
END_PROVIDER END_PROVIDER
@ -18,6 +19,7 @@ END_PROVIDER
BEGIN_PROVIDER [ integer, u2 ] BEGIN_PROVIDER [ integer, u2 ]
integer :: fu integer :: fu
u2 = fu(d3,d4) u2 = fu(d3,d4)
!df
END_PROVIDER END_PROVIDER
integer function fu(x,y) integer function fu(x,y)

3
src/.style.yapf Normal file
View File

@ -0,0 +1,3 @@
[style]
based_on_style = pep8
COLUMN_LIMIT = 100

537
src/build_file.py Normal file
View File

@ -0,0 +1,537 @@
#!/usr/bin/env python
# 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
import os, sys
import irpf90_t
from command_line import command_line
from os.path import basename
irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
irp_id = irpf90_t.irp_id
cwd = os.getcwd()
def dress(f, in_root=False):
#(str,bool) -> str
""" Transfoms the filename into $PWD/IRPF90_temp/f
Note:
In root=True resurn $PWD/f
"""
pwd = os.getcwd()
if in_root:
result = os.path.join(pwd, f)
else:
result = os.path.join(pwd, irpdir, f)
return os.path.normpath(result)
def create_build_touches(l_irp_m, ninja):
irp_id = irpf90_t.irp_id
name = "irp_touches"
short_target_o = "%s.irp.o" % name
short_target_F90 = "%s.irp.F90" % name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
list_of_modules_irp = ' '.join(l_irp_m)
result_ninja = '\n'.join([
"build {target_o}: compile_fortran_{irp_id} {target_F90} | {list_of_modules_irp}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
""
])
result_make = '\n'.join([
"{target_o}: {target_F90} | {list_of_modules_irp}",
'\t@printf "F: {short_target_F90} -> {short_target_o}\\n"',
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", ""
])
result = result_ninja if ninja else result_make
return result.format(**locals())
def create_build_archive(l_irp_o, l_usr_o_wo_main, l_ext_o, l_irp_sup_o, ninja=True):
# (List[str] * 6 ) -> str
"""Create the build command for the irp_touches.o file and the irpf90.a library.
- the touch file need all the irp_module.
- the archive file need all the object.
"""
irp_id = irpf90_t.irp_id
short_lib = "irpf90.a"
lib = dress(short_lib)
list_of_object = ' '.join(l_irp_o + l_usr_o_wo_main + l_ext_o + l_irp_sup_o)
result_ninja = '\n'.join([
"build {lib}: archive_{irp_id} {list_of_object}",
" short_out = {short_lib}",
""])
result_make = '\n'.join([
"{lib}: {list_of_object}",
'\t@printf "Archive: {short_lib}\\n"',
"\t@$(AR) cr $@ $^", ""])
result = result_ninja if ninja else result_make
return result.format(**locals())
def create_build_link(t, l_irp_m, l_usr_m, l_ext_m, ninja=True):
# (Module, List[str], List[str]) -> str
""" Create the build command who will link the .o file into the target executable
To link we need the .o file corresponding to the target, and the ar lib.
"""
irp_id = irpf90_t.irp_id
filename = t.filename
progname = t.prog_name
basename = os.path.basename(filename)
if basename != progname:
from util import logger
logger.info('program-name `{0}` != file-name `{1}` (using file-name for now...)'.format(progname,basename))
target = dress(filename, in_root=True)
short_target = filename
short_target_o = "%s.irp.o" % filename
target_o = dress(short_target_o)
list_of_module = ' '.join(l_irp_m + l_usr_m + l_ext_m)
irp_lib = dress("irpf90.a")
result_ninja = '\n'.join([
"build {target}: link_{irp_id} {target_o} {irp_lib} | {list_of_module}",
" short_out = {short_target}",
""])
result_make = '\n'.join([
"{target}:{target_o} {irp_lib} | {list_of_module}",
'\t@printf "Link: {short_target}\\n"',
"\t@$(FC) $^ $(LIB) -o $@",
""])
result = result_ninja if ninja else result_make
return result.format(**locals())
def create_build_compile(t, l_module, l_ext_modfile=[], ninja=True):
# (Module, List[Module], List[str], bool) -> str
"""Create the build command for the module t.
- The module can produce a .MOD file
- The module can Need another .MOD file.
This .MOD file can be produced by:
1) a file generated by IRP_F90 preprocessor.
2) a file defined by the user but a .irp.f90 file.
3) a file not handle at all by IRPF90.
- The fortran90 file maybe created by the Python module need no dependency.
"""
irp_id = irpf90_t.irp_id
name = t.filename
short_target = name
target = dress(name, in_root=True)
short_target_o = "%s.irp.o" % name
short_target_F90 = "%s.irp.F90" % name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
# Here is the hack. We don't check MOD files, but the associated .o.
# MOD name are not part of the standart.
needed_modules = [dress(x, in_root=True) for x in l_ext_modfile]
# Expensive and stupid. We can create a dict to do the loockup only once
for m in t.needed_modules_usr:
# m is name
for x in l_module:
if m in x.gen_mod and x.filename != t.filename:
needed_modules.append("%s.irp.o" % x.filename)
from util import uniquify
needed_modules = uniquify(needed_modules)
needed_modules_irp = [
"%s.irp.module.o" % (x.filename) for x in l_module if x.name in t.needed_modules_irp
]
if t.has_irp_module:
short_target_module_F90 = "%s.irp.module.F90" % name
short_target_module_o = "%s.irp.module.o" % name
target_module_o = dress(short_target_module_o)
target_module_F90 = dress(short_target_module_F90)
needed_modules_irp += [target_module_o]
list_of_modules = ' '.join(map(dress, needed_modules))
list_of_modules_irp = ' '.join(map(dress, needed_modules_irp))
inline_include = True
if not inline_include:
#Wrong name, this not work!
#list_of_includes = ' '.join(map(lambda x: dress(x, in_root=True), t.includes))
raise NotImplemented
else:
#The include have already by included
list_of_includes = ' '
l_build = [
"build {target_o}: compile_fortran_{irp_id} {target_F90} | {list_of_includes} {list_of_modules} {list_of_modules_irp}",
" short_in = {short_target_F90}",
" short_out = {short_target}",
""
]
l_build_make = [
"{target_o}: {target_F90} | {list_of_includes} {list_of_modules} {list_of_modules_irp}",
'\t@printf "F: {short_target_F90} -> {short_target}\\n"',
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", ""
]
# No need of module when compiling the irp_module.
if t.has_irp_module:
l_build += [
"build {target_module_o}: compile_fortran_{irp_id} {target_module_F90} | {list_of_includes} {list_of_modules} ",
" short_in = {short_target_module_F90}",
" short_out = {short_target_module_o}",
""
]
l_build_make += [
"{target_module_o}: {target_module_F90} | {list_of_includes} {list_of_modules}",
'\t@printf "F: {short_target_module_F90} -> {short_target_module_o}\\n"',
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", ""
]
l_cur = l_build if ninja else l_build_make
return '\n'.join(l_cur).format(**locals())
def create_build_remaining(f,ninja):
"""
Create the build command for the remaining file f. f is a file name (str).
"""
irp_id = irpf90_t.irp_id
t, extension = f.rsplit('.', 1)
t1 = dress(t, in_root=True)
t2 = dress(t, in_root=False)
target_i = f
target_o = "%s.o" % t
if not target_o.startswith(os.path.join(cwd, irpdir)):
target_o = target_o.replace(cwd, os.path.join(cwd, irpdir))
short_target_o = os.path.split(target_o)[1]
short_target_i = os.path.split(target_i)[1]
if extension.lower() in ['f', 'f90']:
result = ["build {target_o}: compile_fortran_{irp_id} {target_i}"]
elif extension.lower() in ['c']:
result = ["build {target_o}: compile_c_{irp_id} {target_i}"]
elif extension.lower() in ['cxx', 'cpp']:
result = ["build {target_o}: compile_cxx_{irp_id} {target_i}"]
result += [" short_in = {short_target_i}", " short_out = {short_target_o}", ""]
return '\n'.join(result).format(**locals())
def create_makefile(d_flags,d_var,irpf90_flags,ninja=True):
result = ["IRPF90= irpf90",
"IRPF90FLAGS= %s" % irpf90_flags,
"BUILD_SYSTEM= %s" % ('ninja' if ninja else 'make'),
""]
# Export all the env variable used by irpf90
result += ['.EXPORT_ALL_VARIABLES:',
'',
'\n'.join("{0} = {1}".format(k, v) for k, v in sorted(d_flags.iteritems())),
'',
'\n'.join("{0} = {1}".format(k, ' '.join(v)) for k, v in sorted(d_var.iteritems())),
'']
result += [ r'# Dark magic below modify with caution!',
r'# "You are Not Expected to Understand This"',
r"# .",
r"# /^\ .",
r'# /\ "V",',
r"# /__\ I O o",
r"# //..\\ I .",
r"# \].`[/ I",
r"# /l\/j\ (] . O",
r"# /. ~~ ,\/I .",
r"# \\L__j^\/I o",
r"# \/--v} I o .",
r"# | | I _________",
r"# | | I c(` ')o",
r"# | l I \. ,/",
r"# _/j L l\_! _//^---^\\_",
r""]
result += ["",
"ifeq ($(BUILD_SYSTEM),ninja)",
"\tBUILD_FILE=IRPF90_temp/build.ninja",
"\tIRPF90FLAGS += -j",
"else ifeq ($(BUILD_SYSTEM),make)",
"\tBUILD_FILE=IRPF90_temp/build.make",
"\tBUILD_SYSTEM += -j",
"else",
"DUMMY:",
"\t$(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)')",
"endif"]
result += ["",
"define run_and_touch",
" $(BUILD_SYSTEM) -C $(dir $(1) ) -f $(notdir $(1) ) $(addprefix $(CURDIR)/, $(2)) && touch $(2)",
"endef",
"",
"EXE := $(shell egrep -ri '^\s*program' *.irp.f | cut -d'.' -f1)",
"",
".PHONY: all",
"",
"all: $(BUILD_FILE)",
"\t$(call run_and_touch, $<, $(EXE))",
"",
".NOTPARALLEL: $(EXE)",
"$(EXE): $(BUILD_FILE)",
"\t$(call run_and_touch, $<, $(EXE))",
"$(BUILD_FILE): $(shell find . -maxdepth 2 -path ./IRPF90_temp -prune -o -name '*.irp.f' -print)",
"\t$(IRPF90) $(IRPF90FLAGS)",
"",
"clean:",
'\trm -f -- $(BUILD_FILE) $(EXE)'
'\t$(shell find IRPF90_temp -type f \\( -name "*.o" -o -name "*.mod" -name "*.a" \\) -delete;)',
"veryclean: clean",
"\trm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags"]
import util
data = '%s\n' % '\n'.join(result)
util.lazy_write_file('Makefile',data,conservative=True)
def create_make_all_clean(l_main):
#
'''Create the ALL and CLEAN target of Makefile
Note: Portability doesn't mater. -delete is maybe not posix
but -exec rm {} + is far more ugly!
'''
l_executable =' '.join(dress( t.filename, in_root=True) for t in l_main)
output = [".PHONY : all",
"all: {l_executable}",
"",
".PHONY: clean",
"clean:",
'\tfind . -type f \( -name "*.o" -o -name "*.mod" \) -delete; rm -f {l_executable} --'
""]
return [ '\n'.join(output).format(**locals())]
def create_var_and_rule(d_flags, ninja):
output = ['\n'.join("{0} = {1}".format(k, v) for k, v in d_flags.iteritems())]
if ninja:
output += ["builddir = %s" % os.path.join(cwd, irpdir)]
# Rules
t = [
"rule compile_fortran_{irp_id}",
" command = $FC $FCFLAGS -c $in -o $out",
" description = F : $short_in -> $short_out",
"",
"rule compile_c_{irp_id}",
" command = $CC $CFLAGS -c $in -o $out",
" description = C : $short_in -> $short_out",
"",
"rule compile_cxx_{irp_id}",
" command = $CXX $CXXFLAGS -c $in -o $out",
" description = C++ : $short_in -> $short_out",
"",
"rule archive_{irp_id}",
" command = $AR cr $out $in",
" description = Archive: $short_out",
"",
"rule link_{irp_id}",
" command = $FC $FCFLAGS $in $LIB -o $out",
" description = Link: $short_out",
""
]
output += ['\n'.join(t).format(irp_id=irpf90_t.irp_id, **d_flags)]
return output
# Environment variables
d_default = {
"FC": "gfortran",
"FCFLAGS": "-O2",
"AR": "ar",
"RANLIB": " ranlib",
"CC": "gcc",
"CFLAGS": "-O2",
"CXX": "g++",
"CXXFLAGS": "-O2",
"LIB": ""}
d_flags = dict()
for k, v in d_default.iteritems():
d_flags[k] = os.environ[k] if k in os.environ else v
include_dir = ' ' + ' '.join(["-I %s" % (i) for i in command_line.include_dir])
d_var = dict()
for k in ['SRC', 'OBJ']:
d_var[k] = os.environ[k].split() if k in os.environ else []
def create_generalmakefile(ninja):
create_makefile(d_flags,d_var, include_dir,ninja)
def run(d_module, ninja):
#(Dict[str,Module],bool) -> str
"""Wrote the ninja file needed to compile the program
Note:
- FC,AR,CC,CXX,LIB, FCFLAGS, CFLAGS, CXXFLAGS are compiler enviroment read
- SRC,OBJ: Are the not irp.f file defined by the user
"""
# Add required flags
for k in ['FCFLAGS', 'CFLAGS', 'CXXFLAGS']:
d_flags[k] += include_dir
# Each python module can produce one or two .F90/.o file and maybe one .MOD file:
#
# No usr defined module and no IRP-F90 provider declaration:
# - One .F90 - No .MOD file
# Usr defined module AND no IRP-F90 provider:
# - One .F90 - One. MOD file
# No usr define module AND IRP-F90 provider:
# - Two .F90 - One. MOD file
# Each python module can depend of different module:
# - IRP created one
# - usr declared
# - external (don't know by IRP)
# Each python module can need 3 type of .MOD file
l_mod = list(d_module.values())
# Modules that are not targets
l_mod_no_main = filter(lambda m: not m.is_main, l_mod)
l_mod_main = filter(lambda m: m.is_main, l_mod)
# List irp supl object/source files
l_irp_sup_o = ["irp_touches.irp.o"]
l_irp_sup_s = ["irp_touches.irp.F90"]
if command_line.do_assert:
l_irp_sup_o += ["irp_stack.irp.o"]
l_irp_sup_s += ["irp_stack.irp.F90"]
if command_line.do_openmp:
l_irp_sup_o += ["irp_locks.irp.o"]
l_irp_sup_s += ["irp_locks.irp.F90"]
if command_line.do_profile:
l_irp_sup_o += ["irp_profile.irp.o", "irp_rdtsc.o"]
l_irp_sup_s += ["irp_profile.irp.F90", "irp_rdtsc.c"]
l_irp_sup_o = map(dress, l_irp_sup_o)
l_irp_sup_s = map(dress, l_irp_sup_s)
# List of extrernal object/source file
l_ext_o = l_ext_m = map(lambda x: dress(x, in_root=True), d_var['OBJ'])
l_ext_s = map(lambda x: dress(x, in_root=True), d_var['SRC'])
# List of object create by the IRP-F90
l_irp_o = l_irp_m = map(dress,
["%s.irp.module.o" % (m.filename) for m in l_mod if m.has_irp_module])
# List of object create by the USR. Maybe he have a module, maybe not.
l_usr_o_wo_main = map(dress, ["%s.irp.o" % (m.filename) for m in l_mod_no_main])
l_usr_m = map(dress, ["%s.irp.o" % (m.filename) for m in l_mod if m.needed_modules_usr])
#-=~=~=
# O U T P U T
#~=~=~=
output = create_var_and_rule(d_flags, ninja)
if not ninja:
output += create_make_all_clean(l_mod_main)
# Create all the .irp.F90 -> .o
for m in l_mod:
output.append(create_build_compile(m, l_mod, l_ext_m, ninja))
output.append(create_build_touches(l_irp_m,ninja))
# All the objects. Kind of, only need usr without main for the static library
output.append(create_build_archive(l_irp_o, l_usr_o_wo_main, l_ext_o, l_irp_sup_o, ninja))
for i in l_mod_main:
# All the mod (overshoot)
output.append(create_build_link(i, l_irp_m, l_usr_m, l_ext_m, ninja))
# Remaining files
for i in l_irp_sup_s[1:]+l_ext_s:
output.append(create_build_remaining(i, ninja))
filename = os.path.join(irpdir, "build.ninja" if ninja else "build.make")
data = '%s\n' % '\n\n'.join(output)
import util
util.lazy_write_file(filename,data,touch=True)
return

View File

@ -1,73 +0,0 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from util import *
from variables import variables
from modules import modules
CHECKPOINT_UNIT_NUMBER=63
FILENAME=irpdir+'irp_checkpoint.irp.F90'
def create():
out_write = [ "subroutine irp_checkpoint_write" ]
l = variables.keys()
l.sort
main_modules = filter(lambda x: modules[x].is_main, modules)
for m in filter(lambda x: not modules[x].is_main, modules):
out_write += [ " use %s"%(modules[m].name) ]
out_write += [ " implicit none" ]
out_write += [ " integer, parameter :: iunit = %d"%(CHECKPOINT_UNIT_NUMBER) ]
out_write += [ " open(unit=%d,file='irp_checkpoint.dat',status='UNKNOWN',action='WRITE')"%(CHECKPOINT_UNIT_NUMBER) ]
for v in l:
var = variables[v]
if var.is_main:
out_write += [ " if (%s_is_built) then"%(v) ]
for w in [v]+var.others:
d = variables[w].dim
if d == []:
out_write += [ " write(iunit,*) '%s', 0"%(w) ]
else:
out_write += [ " write(iunit, *) '%s', %d"%(w, len(d)),
" write(iunit, *) %s"%(",".join(
[ "size(%s,%d)"%(w,i+1) for i in range(len(d)) ] ))
]
out_write += [ " write(iunit,*) %s"%(w) ]
out_write += [ " endif" ]
out_write += [ " close(%d)"%(CHECKPOINT_UNIT_NUMBER) ]
out_write += [ "end" ]
out = '\n'.join(out_write)
if not same_file(FILENAME,out):
file = open(FILENAME,'w')
file.writelines(out)
file.close()
if __name__ == '__main__':
create()

View File

@ -63,8 +63,7 @@ end
precondition = "" precondition = ""
else: else:
precondition = "PROVIDE "+precondition precondition = "PROVIDE "+precondition
file = open(filename,'w')
file.write(template%locals())
file.close()
from util import lazy_write_file
lazy_write_file(filename,template%locals())

View File

@ -24,6 +24,11 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
try:
import irpy
except:
import lib_irpy as irpy
import getopt, sys import getopt, sys
from version import version from version import version
@ -52,6 +57,7 @@ options['t'] = [ 'touch' , 'Display which entities are touched when touch
options['v'] = [ 'version' , 'Prints version of irpf90', 0 ] options['v'] = [ 'version' , 'Prints version of irpf90', 0 ]
options['w'] = [ 'warnings' , 'Activate Warnings', 0 ] options['w'] = [ 'warnings' , 'Activate Warnings', 0 ]
options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ] options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ]
options['G'] = [ 'graph' , 'Print the dependecy-graph of the entities (dots format)', 0 ]
class CommandLine(object): class CommandLine(object):
@ -61,17 +67,16 @@ class CommandLine(object):
self.argv = list(sys.argv) self.argv = list(sys.argv)
self.executable_name = self.argv[0] self.executable_name = self.argv[0]
@irpy.lazy_property
def defined(self): def defined(self):
if '_defined' not in self.__dict__: return [ a for o,a in self.opts if o in [ "-D", '--'+options['D'][0] ] ]
self._defined = []
for o,a in self.opts:
if o in [ "-D", '--'+options['D'][0] ]:
self._defined.append(a)
return self._defined
defined = property(fget=defined)
@irpy.lazy_property
def graph(self):
return next((a.split() for o,a in self.opts if o in ["-G", '--'+options['G'][0] ]),[])
@irpy.lazy_property
def include_dir(self): def include_dir(self):
if '_include_dir' not in self.__dict__:
self._include_dir = [] self._include_dir = []
for o,a in self.opts: for o,a in self.opts:
if o in [ "-I", '--'+options['I'][0] ]: if o in [ "-I", '--'+options['I'][0] ]:
@ -81,20 +86,13 @@ class CommandLine(object):
a = a+'/' a = a+'/'
self._include_dir.append(a) self._include_dir.append(a)
return self._include_dir return self._include_dir
include_dir = property(fget=include_dir)
@irpy.lazy_property
def inline(self): def inline(self):
if '_inline' not in self.__dict__: return next( (a for o,a in self.opts if o in [ "-n", '--'+options['n'][0] ]),'')
self._inline = ""
for o,a in self.opts:
if o in [ "-n", '--'+options['n'][0] ]:
self._inline = a
break
return self._inline
inline = property(fget=inline)
@irpy.lazy_property
def substituted(self): def substituted(self):
if '_substituted' not in self.__dict__:
self._substituted = {} self._substituted = {}
for o,a in self.opts: for o,a in self.opts:
if o in [ "-s", '--'+options['s'][0] ]: if o in [ "-s", '--'+options['s'][0] ]:
@ -102,19 +100,17 @@ class CommandLine(object):
v_re = re.compile(r"(\W)(%s)(\W.*$|$)"%k.strip()) v_re = re.compile(r"(\W)(%s)(\W.*$|$)"%k.strip())
self._substituted[k] = [v, v_re] self._substituted[k] = [v, v_re]
return self._substituted return self._substituted
substituted = property(fget=substituted)
@irpy.lazy_property
def codelet(self): def codelet(self):
if '_codelet' not in self.__dict__:
self._codelet = []
for o,a in self.opts: for o,a in self.opts:
if o in [ "-c", '--'+options['c'][0] ]: if o in [ "-c", '--'+options['c'][0] ]:
buffer = a.split(':') buffer = a.split(':')
filename = 'codelet_'+buffer[0]+'.irp.f' filename = 'codelet_'+buffer[0]+'.irp.f'
if len(buffer) == 2: if len(buffer) == 2:
self._codelet = [buffer[0], int(buffer[1]), None, filename] return [buffer[0], int(buffer[1]), None, filename]
elif len(buffer) == 3: elif len(buffer) == 3:
self._codelet = [buffer[0], int(buffer[2]), buffer[1], filename] return [buffer[0], int(buffer[2]), buffer[1], filename]
else: else:
print """ print """
Error in codelet definition. Use: Error in codelet definition. Use:
@ -123,80 +119,38 @@ or
--codelet=provider:precondition:NMAX --codelet=provider:precondition:NMAX
""" """
sys.exit(1) sys.exit(1)
return self._codelet
codelet = property(fget=codelet)
@irpy.lazy_property
def preprocessed(self): def preprocessed(self):
if '_preprocessed' not in self.__dict__: return [a for o,a in self.ops if o in [ "-p", '--'+options['p'][0] ] ]
self._preprocessed = []
for o,a in self.opts:
if o in [ "-p", '--'+options['p'][0] ]:
self._preprocessed.append(a)
return self._preprocessed
preprocessed = property(fget=preprocessed)
@irpy.lazy_property
def touched(self): def touched(self):
if '_touched' not in self.__dict__: return [a for o,a in self.ops if o in [ "-t", '--'+options['t'][0] ] ]
self._touched = []
for o,a in self.opts:
if o in [ "-t", '--'+options['t'][0] ]:
self._touched.append(a.lower())
return self._touched
touched = property(fget=touched)
@irpy.lazy_property
def align(self): def align(self):
if '_align' not in self.__dict__: return next( (a for o,a in self.opts if o in [ "-l", '--'+options['l'][0] ]),'1')
self._align = '1'
for o,a in self.opts:
if o in [ "-l", '--'+options['l'][0] ]:
self._align = a
return self._align
align = property(fget=align)
@irpy.lazy_property
def coarray(self): def coarray(self):
if '_coarray' not in self.__dict__: return any(o for o,a in self.opts if o in [ "-C", '--'+options['C'][0] ])
self._coarray = False
for o,a in self.opts:
if o in [ "-C", '--'+options['C'][0] ]:
self._coarray = True
return self._coarray
coarray = property(fget=coarray)
@irpy.lazy_property
def warnings(self): def warnings(self):
if '_warnings' not in self.__dict__: return any(o for o,a in self.opts if o in [ "-W", '--'+options['W'][0] ])
self._warnings= False
for o,a in self.opts:
if o in [ "-w", '--'+options['w'][0] ]:
self._warnings= True
return self._warnings
do_warnings = property(fget=warnings)
@irpy.lazy_property
def openmp(self): def openmp(self):
if '_openmp' not in self.__dict__: return any(o for o,a in self.opts if o in [ "-z", '--'+options['z'][0] ])
self._openmp = False
for o,a in self.opts:
if o in [ "-z", '--'+options['z'][0] ]:
self._openmp = True
return self._openmp
do_openmp = property(fget=openmp)
@irpy.lazy_property
def ninja(self): def ninja(self):
if '_ninja' not in self.__dict__: return any(o for o,a in self.opts if o in [ "-j", '--'+options['j'][0] ])
self._ninja = False
for o,a in self.opts:
if o in [ "-j", '--'+options['j'][0] ]:
self._ninja = True
return self._ninja
do_ninja = property(fget=ninja)
@irpy.lazy_property
def directives(self): def directives(self):
if '_directives' not in self.__dict__: return not(any(o for o,a in self.opts if o in [ "-r", '--'+options['r'][0] ]))
self._directives = True
for o,a in self.opts:
if o in [ "-r", '--'+options['r'][0] ]:
self._directives = False
return self._directives
directives = property(fget=directives)
def usage(self): def usage(self):
t = """ t = """
@ -252,16 +206,9 @@ do_$LONG = property(fget=do_$LONG)
long = options[short][0] long = options[short][0]
exec t.replace("$LONG",long).replace("$SHORT",short) #in locals() exec t.replace("$LONG",long).replace("$SHORT",short) #in locals()
@irpy.lazy_property
def do_run(self): def do_run(self):
if '_do_run' not in self.__dict__: return not(any( (self.do_version, self.do_help, self.do_preprocess, self.do_touch, self.do_init)))
self._do_run = not ( \
self.do_version or \
self.do_help or \
self.do_preprocess or \
self.do_touch or \
self.do_init )
return self._do_run
do_run = property(fget=do_run)
command_line = CommandLine() command_line = CommandLine()

View File

@ -24,165 +24,170 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
from entity import Entity
from routine import Routine
from irpf90_t import mandir
from util import parmap, build_dim,lazy_write_file
import os
from variable import Variable def do_print_short(entity):
from variables import variables assert type(entity) == Entity
from subroutine import Sub str_ = "{0:<35} : {1:<30} :: {2:<25} {3}".format(entity.prototype.filename[0],
from subroutines import subroutines entity.type,
from irpf90_t import * entity.name,
from util import * build_dim(entity.dim)) # yapf: disable
return [str_]
def do_print_short(file,var):
assert type(var) == Variable
print >>file, "%s : %s :: %s %s"%( \
var.line.filename[0].ljust(35),
var.type.ljust(30),
var.name.ljust(25),
build_dim(var.dim) )
###################################################################### ######################################################################
def process_doc(file,line): def process_doc(line):
assert type(line) == str assert type(line) == str
line = line.strip() line = line.strip()
if line == "": return [line if line else ".br"]
line = ".br"
print >>file, line
###################################################################### ######################################################################
def process_deps(file,l): def process_deps(l):
assert type(l) == list assert isinstance(l, (list, set))
for v in l: return ['%s\n.br' % v for v in sorted(l)]
print >>file, "%s\n.br"%(v,)
###################################################################### ######################################################################
def process_types(file,var): def process_types(entity_input, d_entity):
assert type(var) == Variable assert type(entity_input) == Entity
vars = [var.name] + var.others
for var in vars: l_name = [entity_input.name] + entity_input.others_entity_name
name = var l_entity = [d_entity[name] for name in l_name]
var = variables[var]
Type = var.type l = [ "{0}\t:: {1}\t{2}".format(entity.type, name, build_dim(entity.dim) )
dim = build_dim(var.dim) for name,entity in zip(l_name,l_entity) ] # yapf: disable
print >>file, "%s\t:: %s\t%s"%(Type,name,dim)
return l
###################################################################### ######################################################################
def do_print(var): def do_print(entity, d_entity):
assert type(var) == Variable assert type(entity) == Entity
filename = var.line.filename[0] filename = entity.prototype.filename[0]
name = var.name name = entity.name
file = open("%s%s.l"%(mandir,var.name), "w")
print >>file, '.TH "IRPF90 entities" l %s "IRPF90 entities" %s'%(name,name) l_data = []
if var.same_as != var.name:
var = variables[var.same_as] l_data.append('.TH "IRPF90 entities" l {0} "IRPF90 entities" {0}'.format(name))
print >>file, ".SH Declaration"
print >>file, ".nf" if entity.same_as != entity.name:
process_types(file,var) entity = d_entity[entity.same_as]
print >>file, ".ni" l_data.extend([".SH Declaration", ".nf"])
if var.doc != []: l_data += process_types(entity, d_entity)
print >>file, ".SH Description"
for l in var.doc: l_data.append(".ni")
process_doc(file,l)
print >>file, ".SH File\n.P" if entity.doc:
print >>file, filename l_data.append(".SH Description")
if var.needs != []: for l in entity.doc:
var.needs.sort() l_data += process_doc(l)
print >>file, ".SH Needs"
process_deps(file,var.needs) l_data.append(".SH File\n.P")
if var.needed_by != []: l_data.append(filename)
var.needed_by.sort()
print >>file, ".SH Needed by" if entity.needs:
process_deps(file,var.needed_by) l_data.append(".SH Needs")
print >>file, ".SH Instability factor" l_data += process_deps(entity.needs)
fo = len(var.children)
fi = len(var.parents) if entity.needed_by:
print >>file, "%5.1f %%"%(100.* (fi / (fi+fo+.000001) )) l_data.append(".SH Needed by")
print >>file, ".br" l_data += process_deps(entity.needed_by)
file.close()
l_data.append(".SH Instability factor")
fo = len(entity.children)
fi = len(entity.parents)
l_data.append("%5.1f %%" % (100. * (fi / (fi + fo + .000001))))
l_data.append(".br")
str_ = '\n'.join(l_data)
lazy_write_file("%s%s.l" % (mandir, name), '%s\n' % str_)
######################################################################
def process_declaration_subroutine(file, sub):
print >>file, sub.line.text.split('!')[0].strip()
# for line in sub.text:
###################################################################### ######################################################################
def do_print_subroutines(sub): def do_print_subroutines(sub):
assert type(sub) == Sub assert type(sub) == Routine
filename = sub.line.filename filename = sub.prototype.filename
name = sub.name name = sub.name
file = open("%s%s.l"%(mandir,sub.name), "w") l_data = []
print >>file, '.TH "IRPF90 entities" l %s "IRPF90 entities" %s'%(name,name)
print >>file, ".SH Declaration" l_data.append('.TH "IRPF90 entities" l {0} "IRPF90 entities" {0}'.format(name))
print >>file, ".nf" l_data.append(".SH Declaration")
process_declaration_subroutine(file,sub) l_data.append(".nf")
print >>file, ".ni" l_data += [sub.prototype.text]
if sub.doc != []: l_data.append(".ni")
print >>file, ".SH Description" if sub.doc:
l_data.append(".SH Description")
for l in sub.doc: for l in sub.doc:
process_doc(file,l) l_data += process_doc(l)
print >>file, ".SH File\n.P" l_data.append(".SH File\n.P")
print >>file, filename
if sub.needs != []: l_data.append(filename)
sub.needs.sort() if sub.needs:
print >>file, ".SH Needs" l_data.append(".SH Needs")
process_deps(file,sub.needs) l_data += process_deps(sub.needs)
if sub.called_by != []:
sub.called_by.sort() if sub.called_by:
print >>file, ".SH Called by" l_data.append(".SH Called by")
process_deps(file,sub.called_by) l_data += process_deps(sub.called_by)
if sub.calls != []:
sub.calls.sort() if sub.calls:
print >>file, ".SH Calls" l_data.append(".SH Calls")
process_deps(file,sub.calls) l_data += process_deps(sub.calls)
if sub.touches != []:
sub.touches.sort() if sub.touches:
print >>file, ".SH Touches" l_data.append(".SH Touches")
process_deps(file,sub.touches) l_data += process_deps(sub.touches)
print >>file, ".SH Instability factor"
l_data.append(".SH Instability factor")
fo = len(sub.needs) + len(sub.calls) + len(sub.touches) fo = len(sub.needs) + len(sub.calls) + len(sub.touches)
fi = len(sub.called_by) fi = len(sub.called_by)
print >>file, "%5.1f %%"%(100.* (fi / (fi+fo+.000001) )) l_data.append("%5.1f %%" % (100. * (fi / (fi + fo + .000001))))
print >>file, ".br" l_data.append(".br")
file.close()
str_ = '\n'.join(l_data)
return '%s\n' % str_
#lazy_write_file(filename="%s.l" % os.path.join(mandir, name), text='%s\n' % str_)
###################################################################### ######################################################################
def run(): def run(d_entity, d_routine):
import parsed_text
import os,sys for v in d_entity.values():
pid1 = os.fork() do_print(v, d_entity)
if pid1 == 0:
for v in variables.values(): l_subs = d_routine.values()
do_print(v)
for s in subroutines.values(): l_data_to_write = [("%s.l" % os.path.join(mandir, s.name), do_print_subroutines(s)) for s in l_subs]
do_print_subroutines(s)
sys.exit(0)
def worker(l):
filename, text = l
lazy_write_file(filename, text)
parmap(worker, l_data_to_write)
pid2 = os.fork()
if pid2 == 0:
tags = [] tags = []
l = variables.keys()
file = open("irpf90_entities","w")
l.sort()
for v in l:
do_print_short(file,variables[v])
line = variables[v].line
# tags.append( '%s\t%s\t/%s/;"\n'%(v,line.filename[0],line.text.split('!')[0].strip()) )
tags.append( '%s\t%s\t%d\n'%(v,line.filename[0],line.i) )
file.close()
l = subroutines.keys()
for v in l:
line = subroutines[v].line
# tags.append('%s\t%s\t/%s/;"\n'%(v,line.filename,line.text.split('!')[0].strip()))
tags.append('%s\t%s\t%d\n'%(v,line.filename,line.i))
tags.sort()
file = open("tags","w")
for line in tags:
file.write(line)
file.close()
sys.exit(0)
os.waitpid(pid1,0) for v in d_entity.keys():
os.waitpid(pid2,0) line = d_entity[v].prototype
tags.append('%s\t%s\t%d\n' % (v, line.filename[0], line.i))
for v in d_routine.keys():
line = d_routine[v].prototype
tags.append('%s\t%s\t%d\n' % (v, line.filename, line.i))
lazy_write_file("tags", ''.join(sorted(tags)))
l_data = [e for k, v in sorted(d_entity.items()) for e in do_print_short(v)]
str_ = '\n'.join(l_data)
lazy_write_file(filename="irpf90_entities", text='%s\n' % str_)
###################################################################### ######################################################################
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -32,21 +32,10 @@ import os
to_remove = """__init__.py cython_setup.py version.py command_line.py""".split() to_remove = """__init__.py cython_setup.py version.py command_line.py""".split()
ext_modules = [] ext_modules = []
files = os.listdir('.') for f in os.listdir('.') if f.emswith(".py") and not f in to_remove:
for file in to_remove: module = f.split('.')[0]
files.remove(file) ext_modules.append(Extension(module,list(f)))
for file in files: setup(name = 'IRPF90 extensions',
if file.endswith(".py"):
module = file.split('.')[0]
ext_modules += [ Extension(module,[file]) ]
setup(
name = 'IRPF90 extensions',
cmdclass = {'build_ext': build_ext}, cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules ext_modules = ext_modules)
)

726
src/entity.py Normal file
View File

@ -0,0 +1,726 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from util import *
from command_line import command_line
import sys
try:
import irpy
except:
import lib_irpy as irpy
class Entity(object):
'''All lines between BEGIN_PROVIDER and END_PROVIDER included
Note: Those lines can define multiple Provider, one need to pick one.
'''
############################################################
def __init__(self, text, label, name=None, comm_world=None):
# (list[str], str, int, Irpy_comm_world)
'''Instantiate the object.
Args:
text: List of lines between BEGIN_PROVIDER and END_PROVIDER included
int: An unique int id (usefull when profilling)
name: The name of the provider defined after the chosen BEGIN_PROVIDER statement
comm_world: A object to communicate we the external world.
'''
assert type(text) == list
assert len(text) > 0
assert type(text[0]) == Begin_provider
self.label = label
self.text = text
self.same_as = text[0].filename[1]
self.name = name if name else self.same_as
self.comm_world = comm_world
# ~ # ~ # ~
# G l o b a l P r o p e r t y
# ~ # ~ # ~
@irpy.lazy_property
def d_entity(self):
# () -> Dict[str,Entity]
'''Create an alias to the global dictionary of Entity.
Note: Be aware of the possiblity of Cyclic Dependency.
'''
return self.comm_world.d_entity
@irpy.lazy_property
def cm_t_filename_parsed_text(self):
# () -> Tuple[str, Parsed_text]
'''Create an alias to the global tuple for parsed text
Note: self.comm_world.t_filename_parsed_text need d_entity.
Be aware of the possibility of Cyclic Dependency
'''
return self.comm_world.t_filename_parsed_text
@irpy.lazy_property
def d_type_lines(self):
# () -> Dict[Line, Tuple[int,Line] ]
'''Contruct a mapping table between the type of the line and the possition'''
from collections import defaultdict
d = defaultdict(list)
for i, line in enumerate(self.text):
d[type(line)] += [(i, line)]
return d
# ~ # ~ # ~
# M u l t i p l e P r o v i d e r H a n d l e r
# ~ # ~ # ~
@irpy.lazy_property
def is_main(self):
# () -> bool
'''Check if this Entity is the main one
Exemple:
BEGIN_PROVIDER [pi, double precision] &
BEGIN_PROVIDER [e, double preision]
return True for 'pi' and False for 'e'
'''
return self.name == self.same_as
@irpy.lazy_property
def prototype(self):
# () -> Line
'''Find the declaration statement associated with the name of the provider
Exemple:
BEGIN_PROVIDER [pi, double precision] &
BEGIN_PROVIDER [e, double preision]
if self.name == e, will return BEGIN_PROVIDER [e, double preision]
'''
d = self.d_type_lines
return next(line for _,line in d[Begin_provider]+d[Cont_provider] if line.filename[1] == self.name)
@irpy.lazy_property
def others_entity_name(self):
# () -> List[str]
'''Extract the other entity-name defined'''
d = self.d_type_lines
return [line.filename[1] for _,line in d[Begin_provider]+d[Cont_provider] if not line.filename[1] == self.name]
@irpy.lazy_property
def doc(self):
# () -> List[str]
doc = [line.text.lstrip()[1:] for _,line in self.d_type_lines[Doc]]
if not doc:
logger.warning("Entity '%s' is not documented" % (self.name))
return doc
@irpy.lazy_property
def documented(self):
#() -> bool
return bool(self.doc)
# ~ # ~ # ~
# T o u c h / R E A D / W R O T E
# ~ # ~ # ~
@irpy.lazy_property_mutable
def is_written(self):
#() -> bool
'''Check if it will be written on disk'''
return any(self.d_entity[i].is_written for i in self.parents)
@irpy.lazy_property
def writer(self):
if not self.is_main:
result = []
else:
name = self.name
result = [ \
"subroutine writer_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("writer_%s" % (self.name))
result += [\
" character*(%d) :: irp_here = 'writer_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += [ \
" if (.not.%s_is_built) then"%(self.same_as),
" call provide_%s"%(self.same_as),
" endif" ]
result += map(lambda x: " call writer_%s(irp_num)" % (x), self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo" ]
for n in [name] + self.others_entity_name:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='UNKNOWN',action='WRITE')"%(n),
" write(irp_iunit,*) %s%s"%(n,build_dim(self.d_entity[n].dim,colons=True)),
" close(irp_iunit)" ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine writer_%s" % (name))
result.append("")
return result
@irpy.lazy_property_mutable
def is_read(self):
'''Check if it will be read from disk'''
return any(self.d_entity[i].is_read for i in self.parents)
@irpy.lazy_property
def reader(self):
if not self.is_main:
result = []
else:
name = self.name
result = [ \
"subroutine reader_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("reader_%s" % (self.name))
result += [\
" character*(%d) :: irp_here = 'reader_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += map(lambda x: " call reader_%s(irp_num)" % (x), self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo"]
for n in [name] + self.others:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='OLD',action='READ')"%(n),
" read(irp_iunit,*) %s%s"%(n,build_dim(self.cm_d_variable[n].dim,colons=True)),
" close(irp_iunit)" ]
result += [ \
" call touch_%s"%(name),
" %s_is_built = .True."%(name) ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine reader_%s" % (name))
result.append("")
return result
@irpy.lazy_property_mutable
def is_self_touched(self):
'''Cehck if it will be modified (touch)'''
return False
@irpy.lazy_property
def is_touched(self):
'''If any of the children is touched, the entity is touched'''
if self.is_self_touched or any(self.d_entity[i].is_touched for i in self.children):
return True
return False
# ~ # ~ # ~
# INCLUDE, USE, CALL
# ~ # ~ # ~
@irpy.lazy_property
def includes(self):
# () -> str
'''Extract the name of include who need be to be include in this Entity'''
return [line.filename for _,line in self.d_type_lines[Include]]
@irpy.lazy_property
def uses(self):
'''Extract the name of module who are used in this Entity'''
return [line.filename for _,line in self.d_type_lines[Use]]
@irpy.lazy_property
def calls(self):
'''Extract the name ofthe function called by the entity'''
def extract_name(line):
return line.text.split('(', 1)[0].split()[1].lower()
return [extract_name(line) for _,line in self.d_type_lines[Call] ]
# ~ # ~ # ~
# Array Dimension
# ~ # ~ # ~
@irpy.lazy_property
def dim(self):
# () -> List[str]
'''Extract the dimension of the needed array in a form of list of variable name
Exemple:
BEGIN_PROVIDER [real, ao_num ]
-> []
BEGIN_PROVIDER [ real, ao_oneD_p, (ao_num) ]
-> ['ao_num']
BEGIN_PROVIDER [ real, ao_oneD_prim_p, (ao_num,ao_prim_num_max) ]
-> ['ao_num', 'ao_prim_num_max']
'''
line = self.prototype.text.split('!')[0]
buffer = line.replace(']', '').split(',', 2)
try:
x = buffer[2].strip()
except IndexError:
return []
else:
return map(str.strip, x[1:-1].split(','))
@irpy.lazy_property
def allocate(self):
# () -> List[Str]
'''Return a list of name of entity who are array and main'''
if not self.is_main:
return []
else:
# We never go here
return [var for var in self.others_entity_name + [self.name] if self.d_entity[var].dim]
# ~ # ~ # ~
# D e c l a r a t i o n
# ~ # ~ # ~
@irpy.lazy_property
def type(self):
# () -> str
'''Compute the fortran type code of the entity'''
type_ = self.prototype.text.split(',')[0].split('[')[1].strip()
if not type_:
logger.error( "Error in definition of %s." % (self.name))
sys.exit(1)
if self.dim:
return "%s, allocatable" % (type_)
else:
return type_
@irpy.lazy_property
def header(self):
# () -> List[str]
'''Compute all the code needed to inistanticant the entity'''
name = self.name
str_ = " {type_} :: {name} {dim}".format(type_=self.type, name=name, dim=build_dim(self.dim, colons=True))
if command_line.coarray:
if not self.dim:
str_ += " [*]"
else:
str_ += " [:]"
l = [str_]
if self.dim and command_line.align != '1':
l += [" !DIR$ ATTRIBUTES ALIGN: %s :: %s" % (command_line.align, name)]
if self.is_main:
l += [" logical :: %s_is_built = .False." % (name)]
return l
############################################################
@irpy.lazy_property
def fmodule(self):
# () -> str
'''Contruct the name of the module who will contain the entity'''
name = self.prototype.filename[0].replace('/', '__').split('.irp.f')[0]
return '%s_mod' % name
############################################################
@irpy.lazy_property
def regexp(self):
# () -> Regex
'''Compile a regex targeted to 'search' the name of this entity'''
import re
return re.compile(r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)" % (self.name), re.I).search
# ~ # ~ # ~
# F o r t r a n 9 0 G e n e r a t i o n
# ~ # ~ # ~
@irpy.lazy_property
def toucher(self):
# () -> List[str]
'''Fabric the f90 routine who handle the cache invalidation'''
# Only one by EntityColleciton
if not self.is_main:
return []
parents = self.parents
name = self.name
result = ["subroutine touch_%s" % (name)]
result += build_use(parents+[name],self.d_entity)
result.append(" implicit none")
if command_line.do_debug:
length = str(len("touch_%s" % (name)))
result += [" character*(%s) :: irp_here = 'touch_%s'" % (length, name)]
result += [" call irp_enter(irp_here)"]
result += map(lambda x: " %s_is_built = .False." % (x), parents)
result.append(" %s_is_built = .True." % (name))
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine touch_%s" % (name))
result.append("")
return result
##########################################################
@irpy.lazy_property
def locker(self):
if not command_line.do_openmp:
return []
name = self.name
result = ["subroutine irp_lock_%s(set)" % (name)]
result += [
" use omp_lib",
" implicit none",
" logical, intent(in) :: set",
" integer(kind=omp_nest_lock_kind),save :: %s_lock" % (name),
" integer,save :: ifirst",
]
if command_line.do_debug:
length = str(len("irp_lock_%s" % (name)))
result += [
" character*(%s) :: irp_here = 'irp_lock_%s'" % (length, name),
" call irp_enter(irp_here)"
]
result += [
" if (ifirst == 0) then",
" ifirst = 1",
" call omp_init_nest_lock(%s_lock)" % (name),
" endif",
" if (set) then",
" call omp_set_nest_lock(%s_lock)" % (name),
" else",
" call omp_unset_nest_lock(%s_lock)" % (name),
" endif",
]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine irp_lock_%s" % (name))
result.append("")
return result
##########################################################
@irpy.lazy_property
def free(self):
# () -> List[ str ]
'''Compute an part of a subroutine used to free a variable'''
name = self.name
result = ["!",
"! >>> FREE %s" % (name),
" %s_is_built = .False." % (self.same_as)]
if self.dim:
result += [
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name)]
if command_line.do_memory:
result += " print *, 'Deallocating %s'"%(name)
result += [" endif"]
result.append("! <<< END FREE")
return result
##########################################################
@irpy.lazy_property
def provider(self):
# () -> List[str]
'''Create the fortran90 code for the EntityCollection'''
if not self.is_main:
return []
name = self.name
same_as = self.same_as
def dimsize(x):
# (str) -> str
'''Compute the number of element in the array'''
try:
b0, b1 = x.split(':')
except ValueError:
return x
b0_is_digit = b0.replace('-', '').isdigit()
b1_is_digit = b1.replace('-', '').isdigit()
if b0_is_digit and b1_is_digit:
size = str(int(b1) - int(b0) + 1)
elif b0_is_digit:
size = "(%s) - (%d)" % (b1, int(b0) - 1)
elif b1_is_digit:
size = "(%d) - (%s)" % (int(b1) + 1, b0)
else:
size = "(%s) - (%s) + 1" % (b1, b0)
return size
def build_alloc(name):
var = self.d_entity[name]
if var.dim == []:
return []
from util import build_dim
def print_size():
return " " * 5 + "print *, ' size: {0}'".format(build_dim(var.dim))
def check_dimensions():
l = ["(%s>0)" % dimsize(x) for x in var.dim]
str_ = ".and.".join(l)
return " if (%s) then" % (str_)
def dimensions_OK():
result = [" irp_dimensions_OK = .True."]
for i, k in enumerate(var.dim):
result.append(" irp_dimensions_OK = irp_dimensions_OK.AND.(SIZE(%s,%d)==(%s))"
% (name, i + 1, dimsize(k)))
return result
def do_allocate():
if command_line.coarray:
result = " allocate(%s(%s)[*],stat=irp_err)"
else:
result = " allocate(%s(%s),stat=irp_err)"
result = result % (name, ','.join(var.dim))
if command_line.do_memory:
tmp = "\n print *, %s, 'Allocating %s(%s)'"
d = ','.join(self.dim)
result += tmp % ('size(' + name + ')', name, d)
return result
result = [" if (allocated (%s) ) then" % (name)]
result += dimensions_OK()
result += [
" if (.not.irp_dimensions_OK) then", " deallocate(%s,stat=irp_err)" % (name),
" if (irp_err /= 0) then", " print *, irp_here//': Deallocation failed: %s'" %
(name), print_size(), " endif"
]
if command_line.do_memory:
result += [" print *, 'Deallocating %s'" % (name)]
result.append(check_dimensions())
result.append(do_allocate())
result += [\
" if (irp_err /= 0) then",
" print *, irp_here//': Allocation failed: %s'"%(name),
print_size(),
" endif",
" endif",
" endif",
" else" ]
result.append(check_dimensions())
result.append(do_allocate())
result += [
" if (irp_err /= 0) then", " print *, irp_here//': Allocation failed: %s'" %
(name), print_size(), " endif", " endif", " endif"
]
return result
result = []
if command_line.directives and command_line.inline in ["all", "providers"]:
result += ["!DEC$ ATTRIBUTES FORCEINLINE :: provide_%s" % (name)]
result += ["subroutine provide_%s" % (name)]
result += build_use([same_as] + self.to_provide, self.d_entity)
if command_line.do_openmp:
result += [" use omp_lib"]
result.append(" implicit none")
length = len("provide_%s" % (name))
result += [
" character*(%d) :: irp_here = 'provide_%s'" % (length, name),
" integer :: irp_err ",
" logical :: irp_dimensions_OK",
"!$ integer :: nthreads"
]
if command_line.do_openmp:
result.append(" call irp_lock_%s(.True.)" % (same_as))
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_enter(irp_here)")
result += build_call_provide(self.to_provide, self.d_entity)
result += flatten(map(build_alloc, [self.same_as] + self.others_entity_name))
result += [
" if (.not.%s_is_built) then" % (same_as), " call bld_%s" % (same_as),
" %s_is_built = .True." % (same_as), ""
]
result += [" endif"]
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_leave(irp_here)")
if command_line.do_openmp:
result.append(" call irp_lock_%s(.False.)" % (same_as))
result.append("end subroutine provide_%s" % (name))
result.append("")
return result
##########################################################
@irpy.lazy_property
def builder(self):
if not self.is_main:
return []
# ~#~#~#~#~#
# Get the raw text for the builder
# ~#~#~#~#~#
#Next return the first element of the iterator
ps_text = next(text for filename, text in self.cm_t_filename_parsed_text
if self.prototype.filename[0].startswith(filename))
begin = next(i for i, (_, line) in enumerate(ps_text)
if isinstance(line, Begin_provider) if line.filename[1] == self.same_as)
end = next(begin + i for i, (_, line) in enumerate(ps_text[begin:])
if isinstance(line, End_provider))
# Now we now that the text is betern ps_text[begin:end]
_, line_prototype = ps_text[begin]
# ~#~#~#~#~#
# Aded the call to the provider
# ~#~#~#~#~#
text = []
if command_line.do_profile:
text.append(([], Declaration(line_prototype.i,
" double precision :: irp_rdtsc, irp_rdtsc1, irp_rdtsc2",
line_prototype.filename)))
text.append(([], Simple_line(line_prototype.i, " irp_rdtsc1 = irp_rdtsc()",
line_prototype.filename)))
for vars, line in ps_text[begin + 1:end]:
text.append((vars, line))
text += map(lambda x: ([], Simple_line(line.i, x, line.filename)),
build_call_provide(vars, self.d_entity))
# ~#~#~#~#~#
# Create the subroutine.
# ~#~#~#~#~#
result = []
if command_line.directives and command_line.inline in ["all", "builders"]:
result += ["!DEC$ ATTRIBUTES INLINE :: bld_%s" % (same_as)]
# Add the use statement
result += ["subroutine bld_%s" % (self.name)]
result += build_use([self.name] + self.needs, self.d_entity)
import parsed_text
# Move the variable to top, and add the text
parsed_text.move_to_top_list(text, [Declaration, Implicit, Use])
result.extend( line.text for _,line in text if not isinstance(line, (Begin_doc, End_doc, Doc, Cont_provider)))
if command_line.do_profile:
result += [
" irp_rdtsc2 = irp_rdtsc()",
" call irp_set_timer(%d,(irp_rdtsc2-irp_rdtsc1))" % self.label
]
#Close
result.append("end subroutine bld_%s" % (self.name))
return result
##########################################################
@irpy.lazy_property_mutable
def needs(self):
#Set by parsed_text.build_needs(...)
raise AttributeError
@irpy.lazy_property
def children(self):
result = []
for x in self.needs:
result.append(x)
try:
result += self.d_entity[x].children
except RuntimeError:
pass # Exception will be checked after
result = OrderedUniqueList(result)
if self.name in result:
error.fail(self.prototype, "Cyclic dependencies:\n%s" % (str(result)))
return result
##########################################################
@irpy.lazy_property
def parents(self):
if not self.is_main:
return []
result = []
for x in self.needed_by:
result.append(x)
try:
result += self.d_entity[x].parents
except RuntimeError:
pass # Exception will be checked after
result = OrderedUniqueList(result)
if self.name in result:
error.fail(self.prototype, "Cyclic dependencies:\n%s" % (str(self._parents)))
return result

View File

@ -1,66 +0,0 @@
#!/usr/bin/env python
# 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
import sys
from irpf90_t import *
from command_line import command_line
do_warnings = command_line.do_warnings
######################################################################
def fail(line,message):
print """
Error:
-----
"""
print message, '\n'
if line is not None:
assert isinstance(line,Line)
print "file %s ; line %d :\n %s"%(line.filename,line.i,line.text)
sys.exit(1)
######################################################################
def warn(line,message):
if not command_line.do_warnings:
return
if line is not None:
assert isinstance(line,Line)
print """
Warning:
-------
"""
print message, '\n'
print "file %s, line %d:\n %s"%(line.filename,line.i,line.text)
else:
print "Warning: %s"%(message)
######################################################################
if __name__ == '__main__':
line = Empty_line(3,"empty", "testfile")
fail(line, "Message")

View File

@ -1,89 +0,0 @@
#!/usr/bin/env python
# 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
import os
import util
import makefile
import irpf90_t
from command_line import command_line
initialized = False
def init():
global initialized
if initialized:
return
# Create directories
for dir in [ irpf90_t.irpdir, irpf90_t.mandir ]:
try:
wd = os.getcwd()
os.chdir(dir)
os.chdir(wd)
except OSError:
os.mkdir(dir)
for dir in command_line.include_dir:
dir = irpf90_t.irpdir+dir
try:
wd = os.getcwd()
os.chdir(dir)
os.chdir(wd)
except OSError:
os.mkdir(dir)
# Create makefile
makefile.create()
# Copy current files in the irpdir
for dir in ['./']+command_line.include_dir:
try:
os.stat(dir)
except:
print dir,'not in dir'
continue
for filename in os.listdir(dir):
filename = dir+filename
if not filename.startswith(".") and not os.path.isdir(filename):
try:
file = open(filename,"r")
except IOError:
if command_line.do_warnings:
print "Warning : Unable to read file %s."%(filename)
else:
buffer = file.read()
file.close()
if not util.same_file(irpf90_t.irpdir+filename,buffer):
file = open(irpf90_t.irpdir+filename,"w")
file.write(buffer)
file.close()
initialized = True

View File

@ -253,13 +253,8 @@ subroutine irp_trace
enddo enddo
print *, '-------------------------' print *, '-------------------------'
end subroutine end subroutine
""" """
txt = txt.split('\n') util.lazy_write_file(FILENAME,txt)
txt = map(lambda x: x+"\n",txt)
if not util.same_file(FILENAME, txt):
file = open(FILENAME,'w')
file.writelines(txt)
file.close()

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
#cscs /usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using # IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method. # the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA # Copyright (C) 2009 Anthony SCEMAMA
@ -25,8 +24,6 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import vim import vim
import os, sys import os, sys
try: try:
@ -34,9 +31,9 @@ try:
sys.path.insert(0, (wd + "/../src/")) sys.path.insert(0, (wd + "/../src/"))
except: except:
pass pass
sys.setcheckinterval(1000)
from command_line import command_line from command_line import command_line
from irpy_files import Irpy_comm_world
def main(): def main():
@ -44,35 +41,46 @@ def main():
if command_line.do_help: if command_line.do_help:
command_line.usage() command_line.usage()
return
if command_line.do_version: if command_line.do_version:
from version import version from version import version
print version print version
return
from init import init
if command_line.do_init: if command_line.do_init:
init() from build_file import create_generalmakefile
create_generalmakefile(command_line.do_ninja)
return
comm_world = Irpy_comm_world()
if command_line.do_graph:
comm_world.t_filename_parsed_text # Initialize entity need. Dirty I know.
print 'graph { '
for name,entity in comm_world.d_entity.items():
if entity.needs:
print ' {0} -> {1}'.format(name, ' '.join(entity.needs))
print '}'
return
if command_line.do_preprocess: if command_line.do_preprocess:
init() for filename, text in comm_world.preprocessed_text:
from preprocessed_text import preprocessed_text
for filename,text in preprocessed_text:
if filename in command_line.preprocessed: if filename in command_line.preprocessed:
for line in text: for line in text:
print line.text print line.text
return
if command_line.do_touch: if command_line.do_touch:
from variables import variables
for var in command_line.touched: for var in command_line.touched:
if var not in variables: if var not in comm_world.d_entity:
print "%s is not an IRP entity"%(var,) print "%s is not an IRP entity" % var
else: else:
print "Touching %s invalidates the following entities:"%(var,) print "Touching %s invalidates the following entities:" % var
parents = variables[var].parents for x in sorted(d_entity[var].parents):
parents.sort()
for x in parents:
print "- %s" % (x, ) print "- %s" % (x, )
return
if command_line.do_codelet: if command_line.do_codelet:
import profile import profile
@ -83,37 +91,18 @@ def main():
if not command_line.do_run: if not command_line.do_run:
return return
init() comm_world.create_buildfile(command_line.do_ninja)
comm_world.write_modules()
import irp_stack comm_world.create_touches()
irp_stack.create() comm_world.create_man()
import makefile
makefile.create()
from modules import modules, write_module
for m in modules.keys():
write_module(modules[m])
makefile.run()
import touches
touches.create()
# import checkpoint
# checkpoint.create()
import create_man
create_man.run()
if command_line.do_profile: if command_line.do_profile:
import profile import profile
profile.run() profile.run(comm_world.d_entity)
if command_line.do_openmp: if command_line.do_openmp:
import locks comm_world.create_lock()
locks.create()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -24,385 +24,63 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import os
from zlib import crc32
irpdir = "IRPF90_temp/" irpdir = "IRPF90_temp/"
mandir = "IRPF90_man/" mandir = "IRPF90_man/"
from zlib import crc32
import os
irp_id = abs(crc32(os.getcwd())) irp_id = abs(crc32(os.getcwd()))
try:
import irpy
except:
import lib_irpy as irpy
class Line(object): class Line(object):
def __init__(self, i, text, filename): def __init__(self, i, text, filename):
self.i = i self.i = i
self._text = None self.text = text
self.filename = filename self.filename = filename
self._lower = None
self.set_text(text)
def get_text(self): @irpy.lazy_property
return self._text def lower(self):
return self.text.lower()
def set_text(self,value):
self._text = value
self._lower = value.lower()
def get_lower(self):
return self._lower
text = property(fget=get_text, fset=set_text)
lower = property(fget=get_lower)
class Empty_line(Line):
str="Empty_line"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self): def __repr__(self):
return "%20s:%5d : %s"%("Empty_line",self.i,self.text) return "%20s:%5d : %s (%s)" % (type(self).__name__, self.i, self.text, self.filename)
class Simple_line(Line): class LineWithName(Line):
str="Simple_line"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Simple_line",self.i,self.text)
class Declaration(Line): @irpy.lazy_property
str="Declaration" def subname(self):
def __init__(self,i,text,filename): buf = self.lower
Line.__init__(self,i,text,filename) if not buf.endswith(')'):
def __repr__(self): buf += "()"
return "%20s:%5d : %s"%("Declaration",self.i,self.text)
class Continue(Line): l_buf = buf.split('(')
str="Continue" l_name = l_buf[0].split()
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Continue",self.i,self.text)
class Begin_provider(Line): if len(l_name) < 2:
str="Begin_provider" import loger
def __init__(self,i,text,filename): logger.error("Syntax Error: %s" % line)
Line.__init__(self,i,text,filename) sys.exit(1)
def __repr__(self): return l_name.pop()
return "%20s:%5d : %s"%("Begin_provider",self.i,self.text)
class Cont_provider(Line):
str="Cont_provider"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Cont_provider",self.i,self.text)
class End_provider(Line):
str="End_provider"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_provider",self.i,self.text)
class Begin_doc(Line):
str="Begin_doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_doc",self.i,self.text)
class Doc(Line):
str="Doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Doc",self.i,self.text)
class End_doc(Line):
str="End_doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_doc",self.i,self.text)
class Begin_shell(Line):
str="Begin_shell"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_shell",self.i,self.text)
class End_shell(Line):
str="End_shell"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_shell",self.i,self.text)
class Begin_template(Line):
str="Begin_template"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_template",self.i,self.text)
class End_template(Line):
str="End_template"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_template",self.i,self.text)
class Subst(Line):
str="Subst"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Subst",self.i,self.text)
class Assert(Line):
str="Assert"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Assert",self.i,self.text)
class Touch(Line):
str="Touch"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Touch",self.i,self.text)
class SoftTouch(Touch):
str="SoftTouch"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("SoftTouch",self.i,self.text)
class Irp_read(Line):
str="Irp_read"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_read",self.i,self.text)
class Irp_write(Line):
str="Irp_write"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_write",self.i,self.text)
class Irp_If(Line):
str="Irp_If"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_If",self.i,self.text)
class Irp_Else(Line):
str="Irp_Else"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_Else",self.i,self.text)
class Irp_Endif(Line):
str="Irp_Endif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_Endif",self.i,self.text)
class Openmp(Line):
str="Openmp"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Openmp",self.i,self.text)
class Directive(Line):
str="Directive"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Directive",self.i,self.text)
class Use(Line):
str="Use"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Use",self.i,self.text)
class Do(Line):
str="Do"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Do",self.i,self.text)
class Enddo (Line):
str="Enddo"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Enddo",self.i,self.text)
class If(Line):
str="If"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("If",self.i,self.text)
class Elseif(Line):
str="Elseif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Elseif",self.i,self.text)
class Else(Line):
str="Else"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Else",self.i,self.text)
class Endif(Line):
str="Endif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Endif",self.i,self.text)
class Select(Line):
str="Select"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Select",self.i,self.text)
class Case(Line):
str="Case"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Case",self.i,self.text)
class End_select(Line):
str="End_select"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_select",self.i,self.text)
class Program(Line):
str="Program"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Program",self.i,self.text)
class Subroutine(Line):
str="Subroutine"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Subroutine",self.i,self.text)
class Function(Line):
str="Function"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Function",self.i,self.text)
class Call(Line):
str="Call"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Call",self.i,self.text)
class Provide(Line):
str="Provide"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Provide",self.i,self.text)
class NoDep(Line):
str="NoDep"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("NoDep",self.i,self.text)
class Return (Line):
str="Return"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Return",self.i,self.text)
class Include(Line):
str="Include"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Include",self.i,self.text)
class Implicit (Line):
str="Implicit"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Implicit",self.i,self.text)
class Free(Line):
str="Free"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Free",self.i,self.text)
class End(Line):
str="End"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End",self.i,self.text)
class Provide_all (Line):
str="Provide_all"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Provide_all",self.i,self.text)
######################################################################
def create_irpf90_files():
result = []
from command_line import command_line
import os
def is_irpf90_file(filename):
return filename.endswith(".irp.f") and not filename.startswith('.')
result = filter ( is_irpf90_file, os.listdir(os.getcwd()) )
for dir in command_line.include_dir:
try:
os.stat(dir)
result += map(lambda x: dir+x, filter ( is_irpf90_file, os.listdir(dir) ) )
except:
continue
if command_line.do_codelet:
result += [command_line.codelet[3]]
return result
irpf90_files = create_irpf90_files()
l_type = [
'Empty_line', 'Simple_line', "Declaration", "Continue", "Begin_provider",
"Cont_provider", "End_provider", "Begin_doc", "Doc", "End_doc",
"Begin_shell", "End_shell", "Begin_template", "End_template", "Subst",
"Assert", "Touch", "SoftTouch", "Irp_read", "Irp_write", "Irp_If",
"Irp_Else", "Irp_Endif", "Openmp", "Directive", "Use", "Do", "Enddo", "If",
"Elseif", "Else", "Endif", "Select", "Case", "End_select", "Provide", "NoDep", "Return", "Include",
"Implicit", "Free", "End", "Provide_all","Contains",'Type','End_module','Interface','End_interface',
'Where','Elsewhere','Endwhere']
for t in l_type:
globals()[t] = type(t, (Line, ), {})
for t in ['Subroutine', 'Function', 'Program', 'Call','Module']:
globals()[t] = type(t, (LineWithName, ), {})

View File

@ -28,12 +28,13 @@
import os import os
import sys import sys
wd = os.path.abspath(os.path.dirname(__file__)) if __name__ == "__main__":
from irpf90_t import mandir from irpf90_t import mandir
filename = sys.argv[1].lower()+".l" entity = sys.argv[1].lower()
filename = '%s.l'% entity
if filename not in os.listdir(mandir): if filename not in os.listdir(mandir):
print "%s does not exist"%(sys.argv[1]) print "Error: `%s` does not exist"% entity
sys.exit(-1) sys.exit(-1)
os.system("man ./"+mandir+sys.argv[1].lower()+".l") os.system("man %s" % os.path.join(mandir,filename))

322
src/irpy_files.py Normal file
View File

@ -0,0 +1,322 @@
from util import parmap,lazy_write_file
from util import flatten, listdir
try:
import irpy
except:
import lib_irpy as irpy
import os
import irpf90_t
import sys
from command_line import command_line
from util import logger
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(other) for other in ent.others_entity_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):
l_var = line.lower.split()[1:]
if len(l_var) < 1:
error.fail(line, "Syntax error")
if any(v for v in l_var if v not in d_ent):
error.fail(line, "Variable %s unknown" % (v, ))
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.header + 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):
import irp_stack
irp_stack.create()
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
l = sorted(self.d_entity.keys())
out = []
for v in l:
out += self.d_entity[v].locker
out += [ "subroutine irp_init_locks_%s()"%(irpf90_t.irp_id),
" implicit none" ]
for v in l:
out += [ " call irp_lock_%s(.True.)"%v ]
out += [ " call irp_lock_%s(.False.)"%v ]
out += [ "end subroutine", "" ]
filename = os.path.join(irpf90_t.irpdir,'irp_locks.irp.F90')
lazy_write_file(filename, '\n'.join(out))

160
src/lib_irpy.py Executable file
View File

@ -0,0 +1,160 @@
#Handle the execution stack
from collections import defaultdict
d_path = defaultdict(list)
d_last_caller = defaultdict(lambda: None)
def genealogy(obj, _node, direction,degree_max=100):
"""Return the genealogy of a _node.
Direction is $parents or $children, recurse accordingly"""
def sap(_node, direction, visited=set(), degree=0):
visited.add(_node)
try:
s = getattr(obj, "{0}_{1}".format(_node, direction))
except AttributeError:
s = set()
for next_ in s - visited:
if degree < degree_max:
sap(next_, direction, visited, degree+1)
return visited
s = sap(_node, direction) - set([_node])
return s
def addattr(obj, name, value):
try:
s = getattr(obj, name)
except AttributeError:
setattr(obj, name, set([value]))
else:
setattr(obj, name, s | set([value]))
def removeattr(obj, name, value):
try:
s = getattr(obj, name)
except AttributeError:
pass
else:
setattr(obj, name, s - set([value]))
# _
# | \ _ _ _ ._ _. _|_ _ ._
# |_/ (/_ (_ (_) | (_| |_ (_) |
#
class lazy_property(object):
"""
My little Property
My little Property
My little Property... friend
"""
def __init__(self, provider, init_node=False, immutable=True):
"""Provider: If a function who will be used to compute the node
init_node: If the name of the node
immutable: If immutable is set you cannot set the node"""
self.provider = provider
self.init_node = init_node
self.immutable = immutable
if not self.init_node:
name = provider.__name__
else:
name = self.init_node
#Kind of human readable identifier
self._node = "_%s_%s" % (name, id(provider))
def __get__(self, obj, objtype):
"Get the value of the node and handle the genealogy"
_node = self._node
if d_path[obj]:
_caller = d_path[obj][-1]
if _caller != d_last_caller[obj]:
addattr(obj, "%s_parents" % _node, _caller)
addattr(obj, "%s_children" % _caller, _node)
d_last_caller[obj] = _caller
#Wanted: value. Cached or Computed
try:
value = getattr(obj, _node)
except AttributeError:
d_path[obj].append(_node)
value = self.provider(obj)
setattr(obj, _node, value)
d_path[obj].pop()
return value
def __set__(self, obj, value):
"""Set the value of the node
But wait, init_node are "gradual typed" variable! Youpi!
Idea borrowed from the-worst-programming-language-ever (http://bit.ly/13tc6XW)
"""
_node = self._node
if not self.init_node:
if self.immutable:
raise AttributeError("Immutable Node {0}".format(self._node))
#Set the new value
setattr(obj, _node, value)
#Node ancestor need to be recompute is asked
for _parent in genealogy(obj, _node, "parents"):
if hasattr(obj, _parent): delattr(obj, _parent)
#Node abandoned her children,
for _child in genealogy(obj, _node, "children",degree_max=1):
removeattr(obj, "%s_parents" % _child, _node)
#Indeed node is now a leaf
setattr(obj, "%s_children" % _node, set())
else:
setattr(obj, _node, value)
self.init_node = False
def lazy_property_mutable(provider):
"Return a lazy_property mutable"
return lazy_property(provider=provider, immutable=False)
def lazy_property_leaves(mutables=(), immutables=()):
"Set to properties for the __init__ method"
def leaf_decorator(func):
def func_wrapper(self, *args, **kwargs):
for node in set(immutables) | set(mutables):
def provider(self):
return getattr(self, "_%s" % node)
p = lazy_property(provider=provider,
init_node=node,
immutable=node in immutables)
#If this ugly? Yeah... Is this an issue? I don't really know
setattr(self.__class__, node, p)
return func(self, *args, **kwargs)
return func_wrapper
return leaf_decorator

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
# 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
from command_line import command_line
from irpf90_t import *
from util import *
from variables import variables
FILENAME=irpdir+'irp_locks.irp.F90'
def create():
out = []
l = variables.keys()
l.sort
for v in l:
var = variables[v]
out += var.locker
out += [
"subroutine irp_init_locks_%s()"%(irp_id),
" implicit none" ]
for v in l:
out += [ " call irp_lock_%s(.True.)"%v ]
out += [ " call irp_lock_%s(.False.)"%v ]
out += [ "end subroutine" ]
out = map(lambda x: "%s\n"%(x),out)
if not same_file(FILENAME,out):
file = open(FILENAME,'w')
file.writelines(out)
file.close()
if __name__ == '__main__':
create()

View File

@ -1,204 +0,0 @@
#!/usr/bin/env python
# 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
import os,sys
import irpf90_t
from command_line import command_line
irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
FILENAME = "Makefile"
FILENAME_GITIGNORE = ".gitignore"
IRPF90_MAKE = "irpf90.make"
######################################################################
def create():
has_makefile = True
try:
file = open(FILENAME,"r")
except IOError:
has_makefile = False
if has_makefile:
return
file = open(FILENAME,"w")
t = """IRPF90 = irpf90 #-a -d
FC = gfortran
FCFLAGS= -O2 -ffree-line-length-none -I .
NINJA = ninja
AR = ar
RANLIB = ranlib
SRC=
OBJ=
LIB=
-include %s
export
%s: $(filter-out %s%%, $(wildcard */*.irp.f)) $(wildcard *.irp.f) $(wildcard *.inc.f) Makefile
\t$(IRPF90)
"""%(IRPF90_MAKE,IRPF90_MAKE,irpdir)
file.write(t)
file.close()
create_gitignore()
######################################################################
def create_gitignore():
has_makefile = True
try:
file = open(FILENAME_GITIGNORE,"r")
except IOError:
has_makefile = False
if has_makefile:
return
file = open(FILENAME_GITIGNORE,"w")
t = "\n".join([ irpdir, mandir, IRPF90_MAKE, 'irpf90_entities', 'tags' ])
file.write(t)
file.close()
######################################################################
def run_ninja():
import ninja
ninja.run()
######################################################################
def run_make():
from modules import modules
mod = []
for m in modules.values():
mod.append(m)
file = open(IRPF90_MAKE,'w')
result = ""
result += "FC+=-I %s "%(irpdir)
for i in command_line.include_dir:
result += "-I %s%s "%(irpdir,i)
result += "\n"
result += "SRC += %sirp_stack.irp.F90"%(irpdir)
result += " %sirp_touches.irp.F90"%(irpdir)
# result += " %sirp_checkpoint.irp.F90"%(irpdir)
if command_line.do_openmp:
result += " %sirp_locks.irp.F90"%(irpdir)
if command_line.do_profile:
result += " %sirp_profile.irp.F90"%(irpdir)
for m in mod:
result += " %s%s.irp.F90"%(irpdir,m.filename)
result += " %s%s.irp.module.F90"%(irpdir,m.filename)
print >>file, result
result = "OBJ_IRP = %sirp_stack.irp.o "%(irpdir)
for m in mod:
if not m.is_main:
result += " %s%s.irp.o"%(irpdir,m.filename)
result += " %s%s.irp.module.o"%(irpdir,m.filename)
print >>file, result
print >>file, "OBJ1 = $(OBJ_IRP) $(OBJ) %sirp_touches.irp.o "%(irpdir),
# print >>file, " %sirp_checkpoint.irp.o"%(irpdir),
if command_line.do_profile:
print >>file, " %sirp_profile.irp.o"%(irpdir), " irp_rdtsc.o",
if command_line.do_codelet:
print >>file, " irp_rdtsc.o",
if command_line.do_openmp:
print >>file, " %sirp_locks.irp.o"%(irpdir)
else:
print >>file, ""
all = filter(lambda x: modules[x].is_main, modules)
all = map(lambda x: x[:-6], all)
all_o = map(lambda x: "%s.irp.module.o %s.irp.o"%(x,x), all)
print >>file, "ALL = %s"%(" ".join(all))
print >>file, "ALL_OBJ = %s"%(" ".join(all_o))
print >>file, "ALL_OBJ1 = $(patsubst %%, %s%%,$(notdir $(ALL_OBJ)))"%(irpdir)
print >>file, "all:$(ALL)"
print >>file, "\t@$(MAKE) -s move"
# print >>file, "ifdef USE_IRPF90_A"
for m in mod:
if m.is_main:
exe = m.filename
print >>file, "%s: %s%s.irp.o %s%s.irp.module.o IRPF90_temp/irpf90.a"%(exe,irpdir,exe,irpdir,exe)
print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o IRPF90_temp/irpf90.a $(LIB)"%(irpdir,irpdir)
print >>file, "\t@$(MAKE) -s move"
# print >>file, "else"
# for m in mod:
# if m.is_main:
# exe = m.filename
# print >>file, "%s: %s%s.irp.o %s%s.irp.module.o $(OBJ1)"%(exe,irpdir,exe,irpdir,exe)
# print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o $(OBJ1) $(LIB)"%(irpdir,irpdir)
# print >>file, "\t@$(MAKE) -s move"
# print >>file, "endif"
buffer = ""
for m in mod:
filename = "%s%s.irp.o: $(OBJ) %s%s.irp.module.o"%(irpdir,m.filename,irpdir,m.filename)
needed_modules = filter( lambda x: modules[x].name in m.needed_modules, modules )
needed_files = map(lambda x: modules[x].filename, needed_modules)
mds = map (lambda x: " %s%s.irp.module.o"%(irpdir,x),needed_files)
print >>file, filename," ".join(mds)," ".join(m.includes)
if not m.is_main:
buffer += "\t - @echo '"+filename+" ".join(mds)+"' >> %sdist_Makefile\n"%(irpdir)
# print >>file, "%sirp_touches.irp.o %sirp_checkpoint.irp.o: $(OBJ) "%(irpdir,irpdir),
print >>file, "%sirp_touches.irp.o: $(OBJ) "%(irpdir),
mds = filter(lambda x: not x.is_main,mod)
mds = map(lambda x: " %s%s.irp.o %s%s.irp.o"%(irpdir,x.filename,irpdir,x.filename),mds)
print >>file," ".join(mds)
if command_line.do_profile:
print >>file, "%sirp_profile.irp.o:"%(irpdir),
print >>file," ".join(mds)
if command_line.do_openmp:
print >>file, "%sirp_locks.irp.o:"%(irpdir),
print >>file," ".join(mds)
for dir in [ irpdir ] + map(lambda x: irpdir+x, command_line.include_dir):
print >>file, dir+"%.irp.module.o: $(OBJ) "+dir+"%.irp.module.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.module.F90 -o "+dir+"$*.irp.module.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.module.o "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.o: %.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c $*.F90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f90\n\t$(FC) $(FCFLAGS) -c $*.f90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f\n\t$(FC) $(FCFLAGS) -c $*.f -o "+dir+"$*.o"
print >>file, dir+"%.o: %.F\n\t$(FC) $(FCFLAGS) -c $*.F -o "+dir+"$*.o"
print >>file, dir+"%.irp.F90: "+IRPF90_MAKE+"\n"
print >>file, "move:\n\t@mv -f *.mod IRPF90_temp/ 2> /dev/null | DO_NOTHING=\n"
print >>file, "IRPF90_temp/irpf90.a: $(OBJ) $(OBJ1)\n\t$(AR) crf IRPF90_temp/irpf90.a $(OBJ1)\n"
print >>file, "clean:\n\trm -rf $(EXE) $(OBJ1) IRPF90_temp/irpf90.a $(ALL_OBJ1) $(ALL)\n"
print >>file, "veryclean:\n\t- $(MAKE) clean\n"
print >>file, "\t- rm -rf "+irpdir+" "+mandir+" "+IRPF90_MAKE+" irpf90_entities dist tags\n"
file.close()
######################################################################
def run():
if command_line.do_ninja:
run_ninja()
else:
run_make()

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/unr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using # IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method. # the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA # Copyright (C) 2009 Anthony SCEMAMA
@ -24,18 +24,26 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
from irpf90_t import * from irpf90_t import *
from variable import *
from variables import variables
from command_line import command_line from command_line import command_line
import preprocessed_text import preprocessed_text
from util import * from util import *
from entity import Entity
def put_info(text, filename):
lenmax = 80 - len(filename)
format_ = "%" + str(lenmax) + "s ! %s:%4s"
str_ = '{text:{width}} ! {filename}:{i:4}'
for _, line in text:
line.text = str_.format(text=line.text,filename=line.filename,i=line.i,width=lenmax)
return text
class Fmodule(object): class Fmodule(object):
header = \ header = [ "! -*- F90 -*-",
[ "! -*- F90 -*-",
"!", "!",
"!-----------------------------------------------!", "!-----------------------------------------------!",
"! This file was generated with the irpf90 tool. !", "! This file was generated with the irpf90 tool. !",
@ -44,86 +52,75 @@ class Fmodule(object):
"!-----------------------------------------------!", "!-----------------------------------------------!",
""] ""]
def __init__(self,text,filename): def __init__(self, text, filename, d_variable):
self.text = put_info(text, filename) self.text = put_info(text, filename)
self.filename = filename[:-6] self.filename = filename[:-6]
self.name = "%s_mod" % (self.filename).replace('/', '__').replace('.', 'Dot') self.name = "%s_mod" % (self.filename).replace('/', '__').replace('.', 'Dot')
self.d_all_variable = d_variable
def is_main(self): @irpy.lazy_property
if '_is_main' not in self.__dict__:
self._is_main = self.prog_name is not None
return self._is_main
is_main = property(is_main)
def prog_name(self): def prog_name(self):
if '_prog_name' not in self.__dict__: l = [line.filename for _, line in self.text if isinstance(line, Program)]
buffer = filter(lambda x: type(x[1]) == Program,self.text) return l.pop() if l else None
if buffer == []:
self._prog_name = None
else:
self._prog_name = buffer[0][1].filename
return self._prog_name
prog_name = property(prog_name)
def variables(self): @irpy.lazy_property
if '_variables' not in self.__dict__: def is_main(self):
from variables import variables return self.prog_name is not None
name = self.name
self._variables = filter(lambda x: variables[x].fmodule == name, variables)
return self._variables
variables = property(variables)
@irpy.lazy_property
def l_entity(self):
return [value for value in self.d_all_variable.values() if value.fmodule == self.name]
@irpy.lazy_property
def head(self): def head(self):
if '_head' not in self.__dict__: '''The module who containt the declaration of the entity'''
body = list(self.use)
body += list(self.dec)
body += [header for var in self.l_entity for header in var.header]
if body:
result = ["module %s" % (self.name)] result = ["module %s" % (self.name)]
result += self.use result += body
result += self.dec result += ["end module %s" % (self.name)]
result += flatten( map(lambda x: variables[x].header,self.variables) ) else:
result.append( "end module %s"%(self.name) )
self._head = result
return self._head
head = property(head)
def needed_vars(self):
if '_needed_vars' not in self.__dict__:
result = map(lambda x: variables[x].needs,self.variables)
result = make_single ( flatten(result) )
self._needed_vars = result
return self._needed_vars
needed_vars = property(needed_vars)
def includes(self):
if '_includes' not in self.__dict__:
buffer = []
for v in self.needed_vars:
buffer += variables[v].includes
self._includes = make_single(buffer)
return self._includes
includes = property(includes)
def generated_text(self):
if '_generated_text' not in self.__dict__:
result = [] result = []
for var in self.variables:
var = variables[var] return result
@irpy.lazy_property
def has_irp_module(self):
return bool(self.head)
@irpy.lazy_property
def needed_vars(self):
return set(n for var in self.l_entity for n in var.needs)
@irpy.lazy_property
def includes(self):
return set(i for var in self.needed_vars for i in self.d_all_variable[var].includes)
@irpy.lazy_property
def generated_text(self):
'Routine genereraed by the IRPF90. provide, build, ...'
result = []
for var in self.l_entity:
result += var.provider result += var.provider
result += var.builder result += var.builder
if var.is_read: if var.is_read:
result += var.reader result += var.reader
if var.is_written: if var.is_written:
result += var.writer result += var.writer
self._generated_text = result
return self._generated_text
generated_text = property(generated_text)
def residual_text(self): return result
if '_residual_text' not in self.__dict__:
from variables import build_use, call_provides @irpy.lazy_property
from parsed_text import move_to_top def residual_text_use_dec(self):
def remove_providers(text): def remove_providers(text):
result = [] result = []
inside = False inside = False
for vars, line in text: for vars, line in text:
if type(line) == Begin_provider: if type(line) == Begin_provider:
inside = True inside = True
@ -134,26 +131,45 @@ class Fmodule(object):
return result return result
def modify_functions(text): def modify_functions(text):
result = [] result = []
variable_list = [] variable_list = []
skip_interface = False
for vars, line in text: for vars, line in text:
if type(line) in [ Subroutine, Function ]: if type(line) in [Interface, End_interface]:
skip_interface = not skip_interface
if skip_interface:
result.append((vars, line))
continue
if type(line) in [Subroutine, Function, Program]:
#Deep copy...
variable_list = list(vars) variable_list = list(vars)
elif type(line) == End: elif type(line) == End:
result += map(lambda x: ([],Use(line.i,x,line.filename)), build_use(variable_list)) result += [([], Use(line.i, x, line.filename)) for x in build_use(variable_list, self.d_all_variable)]
else: else:
variable_list += vars variable_list += vars
result.append((vars, line)) result.append((vars, line))
return result return result
def extract_use_dec_text(text): def extract_use_dec_text(text):
inside = False # (List[ Tuple(Entity,Line) ]) -> (List[ Tuple(Entity,Line),List[ Tuple(Entity,Line),List[ Tuple(Entity,Line))
result = [] '''Extract the global declaration statement and module use form the declaration of function. '''
dec = []
use = [] inside = 0
result,dec,use,module = [],[],[],[]
for vars, line in text: for vars, line in text:
if type(line) in [ Subroutine, Function, Program]:
inside = True if isinstance(line, (Subroutine, Function, Program,Interface,Module)):
inside += 1
if type(line) == Module:
module.append((vars,line))
if inside: if inside:
result.append((vars, line)) result.append((vars, line))
else: else:
@ -161,67 +177,93 @@ class Fmodule(object):
use.append((vars, line)) use.append((vars, line))
elif type(line) == Declaration: elif type(line) == Declaration:
dec.append((vars, line)) dec.append((vars, line))
if type(line) == End:
inside = False
return use, dec, result
def provide_variables(text):
result = [] if isinstance(line,(End,End_interface,End_module)):
for vars,line in text: inside += -1
result.append( ([],line) )
result += map(lambda x: ([],Simple_line(line.i,x,line.filename)), call_provides(vars)) if inside:
return result print 'Something wrong append'
sys.exit(1)
return use, module, dec, result
result = remove_providers(self.text) result = remove_providers(self.text)
result = modify_functions(result) result = modify_functions(result)
use,dec,result = extract_use_dec_text(result)
self._use = make_single(map(lambda x: " "+x[1].text, use))
self._dec = map(lambda x: " "+x[1].text, dec)
# self._dec = make_single(map(lambda x: " "+x[1].text, dec))
result = provide_variables(result)
result = move_to_top(result,Declaration)
result = move_to_top(result,Implicit)
result = move_to_top(result,Use)
result = map(lambda x: x[1], result)
result = map(lambda x: x.text, result)
self._residual_text = result
return self._residual_text
residual_text = property(residual_text)
from collections import namedtuple
Residual_text_use_dec = namedtuple('Residual_text_use_dec', ['use', 'module', 'dec', 'result'])
return Residual_text_use_dec(*extract_use_dec_text(result))
@irpy.lazy_property
def use(self): def use(self):
if '_use' not in self.__dict__: return set(" %s" % line.text for _, line in self.residual_text_use_dec.use)
self.residual_text
return self._use
use = property(use)
@irpy.lazy_property
def gen_mod(self):
'''List of module generated by the user in this module...'''
return set("%s" % line.subname for _, line in self.residual_text_use_dec.module)
@irpy.lazy_property
def dec(self): def dec(self):
if '_dec' not in self.__dict__: '''The declaration of this module
self.residual_text
return self._dec Note:
dec = property(dec) Because user can define F90 Type, we need to keep the correct order.
Warning:
If we uniquify that can cause a problem with the type in guess.
```type toto
integer :: n
end type toto
integer :: n
```
Fix:
We need to support Type keyword.
'''
l = [" %s" % line.text for _, line in self.residual_text_use_dec.dec]
from util import uniquify
if len(l) != len(uniquify(l)):
raise NotImplementedError
return l
@irpy.lazy_property
def residual_text(self):
'''Not the generated function (build, provide, touch, etc.)'''
result = []
for vars, line in self.residual_text_use_dec.result:
result.append(([], line))
result += map(lambda x: ([], Simple_line(line.i, x, line.filename)),
build_call_provide(vars, self.d_all_variable))
from parsed_text import move_to_top_list, move_interface
move_to_top_list(result, [Declaration, Implicit, Use])
move_interface(result)
return [line.text for _, line in result]
@irpy.lazy_property
def needed_modules(self): def needed_modules(self):
if '_needed_modules' not in self.__dict__: l = set(x.split(',only').pop(0).split()[1] for x in self.generated_text + self.head + self.residual_text if x.lstrip().startswith("use "))
buffer = filter(lambda x: x.lstrip().startswith("use "), \
self.generated_text+self.head+self.residual_text)
buffer = map(lambda x: x.split()[1], buffer)
buffer = filter(lambda x: x.endswith("_mod"),buffer )
self._needed_modules = make_single(buffer)
if self.name in self._needed_modules:
self._needed_modules.remove(self.name)
return self._needed_modules
needed_modules = property(needed_modules)
###################################################################### if self.name in l:
l.remove(self.name)
return l
@irpy.lazy_property
def needed_modules_irp(self):
return [i for i in self.needed_modules if i.endswith("_mod")]
@irpy.lazy_property
def needed_modules_usr(self):
return [i for i in self.needed_modules if not i.endswith("_mod")]
if __name__ == '__main__':
from parsed_text import parsed_text
for filename, text in parsed_text:
if filename == 'vmc_step.irp.f':
x = Fmodule(text,filename)
break
for line in x.head:
print line
print x.includes

View File

@ -1,68 +0,0 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from parsed_text import parsed_text
from module import Fmodule
from util import *
######################################################################
def create_modules():
result = {}
for filename,text in parsed_text:
result[filename] = Fmodule(text,filename)
return result
modules = create_modules()
######################################################################
def write_module(m):
# Module data
filename = irpdir+m.filename+".irp.module.F90"
text = m.header + m.head
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):
# print filename
file = open(filename,"w")
file.writelines(text)
file.close()
# Subroutines
filename = irpdir+m.filename+".irp.F90"
text = m.header + m.generated_text + m.residual_text
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):
# print filename
file = open(filename,"w")
file.writelines(text)
file.close()
######################################################################
if __name__ == '__main__':
write_module(modules['psi.irp.f'])

View File

@ -1,408 +0,0 @@
#!/usr/bin/env python
# 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
import os,sys
import irpf90_t
from command_line import command_line
from modules import modules
irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
irp_id = irpf90_t.irp_id
FILENAME = os.path.join(irpdir,"build.ninja")
cwd = os.getcwd()
PRINT_WIDTH=50
def dress(f,in_root=False):
"""
Transfoms the filename f into $PWD/IRPF90_temp/f
"""
if in_root:
result = os.path.join(cwd,f)
else:
result = os.path.join(cwd,irpdir,f)
return os.path.normpath(result)
def create_build_touches(list_of_other_o):
"""
Create the build command for the irp_touches.o file and the irpf90.a library.
"""
name = "irp_touches"
short_lib = "irpf90.a"
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
lib = dress(short_lib)
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules ]
list_of_modules = map(dress, needed_modules) + list_of_other_o
list_of_modules = ' '.join(list_of_modules)
result = '\n'.join(
[
"build {target_o}: compile_touches_{id} {target_F90} | {list_of_modules}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
"build {lib}: link_lib_{id} {target_o} {list_of_modules}",
" short_out = {short_lib}",
"",
] )
result = result.format(
id = irp_id ,
lib = lib ,
list_of_modules = list_of_modules ,
short_lib = short_lib ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_o = target_o
)
return result
def create_build_target(t,list_of_other_o):
"""
Create the build command for the target module t. t is a Fmodule object.
"""
name = t.filename
irp_lib = dress("irpf90.a")
target = dress(name,in_root=True)
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
short_target_module_F90 = "%s.irp.module.F90"%name
short_target_module_o = "%s.irp.module.o"%name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
target_module_o = dress(short_target_module_o)
target_module_F90 = dress(short_target_module_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules \
if modules[x].name in t.needed_modules ] + [ target_module_o ]
list_of_o = [ target_o, target_module_o, irp_lib ]
list_of_o = ' '.join(list_of_o)
list_of_modules = map(dress, needed_modules) + list_of_other_o
list_of_modules = ' '.join(list_of_modules)
list_of_includes = ' '.join(map(lambda x: dress(x,in_root=True), t.includes))
result = '\n'.join(
[ "build {target}: link_{id} {list_of_o}",
" short_out = {short_target}",
"",
"build {target_o}: compile_fortran_{id} {target_F90} | {list_of_modules} {list_of_includes}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
"build {target_module_o}: compile_fortran_{id} {target_module_F90}",
" short_in = {short_target_module_F90}",
" short_out = {short_target_module_o}",
"",
] )
result = result.format(
id = irp_id ,
list_of_includes = list_of_includes ,
list_of_modules = list_of_modules ,
list_of_o = list_of_o ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target_module_F90 = os.path.split(target_module_F90)[1] ,
short_target_module_o = os.path.split(target_module_o)[1] ,
short_target = name ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_module_F90 = target_module_F90 ,
target_module_o = target_module_o ,
target_o = target_o ,
target = target
)
return result
def create_build_non_target(t,list_of_other_o):
"""
Create the build command for the non-target module t. t is a Fmodule object.
"""
name = t.filename
target = dress(name,in_root=True)
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
short_target_module_F90 = "%s.irp.module.F90"%name
short_target_module_o = "%s.irp.module.o"%name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
target_module_o = dress(short_target_module_o)
target_module_F90 = dress(short_target_module_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules \
if modules[x].name in t.needed_modules ] + [ target_module_o ]
list_of_modules = map(dress, needed_modules)
list_of_modules = ' '.join(list_of_modules)
list_of_externals = ' '.join([ dress(x,in_root=True) for x in list_of_other_o ])
list_of_includes = ' '.join(map(lambda x: dress(x,in_root=True), t.includes))
result = '\n'.join(
[
"build {target_o}: compile_fortran_{id} {target_F90} | {list_of_modules} {list_of_externals}",
" short_in = {short_target_F90}",
" short_out = {short_target}",
"",
"build {target_module_o}: compile_fortran_{id} {target_module_F90} | {list_of_externals} {list_of_includes}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
] )
result = result.format(
id = irp_id ,
list_of_externals = list_of_externals ,
list_of_includes = list_of_includes ,
list_of_modules = list_of_modules ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target = name ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_module_F90 = target_module_F90 ,
target_module_o = target_module_o ,
target_o = target_o
)
return result
def create_build_remaining(f):
"""
Create the build command for the remaining file f. f is a file name (str).
"""
t, extension = f.rsplit('.',1)
t1 = dress(t,in_root=True)
t2 = dress(t,in_root=False)
target_i = f
target_o = "%s.o"%t
if not target_o.startswith(os.path.join(cwd,irpdir)):
target_o = target_o.replace(cwd,os.path.join(cwd,irpdir))
if extension.lower() in [ 'f', 'f90' ]:
result = [ "build {target_o}: compile_fortran_{id} {target_i}" ]
elif extension.lower() in [ 'c' ]:
result = [ "build {target_o}: compile_c_{id} {target_i}" ]
elif extension.lower() in [ 'cxx', 'cpp' ]:
result = [ "build {target_o}: compile_cxx_{id} {target_i}" ]
result += [ " short_in = {short_target_i}",
" short_out = {short_target_o}", "" ]
result = '\n'.join(result).format(
target_o = target_o,
target_i = target_i,
short_target_o = os.path.split(target_o)[1],
short_target_i = os.path.split(target_i)[1],
id = irp_id
)
return result
def create_irpf90_make(targets):
targets = ' '.join(targets)
result = """NINJA += -C {0}
TARGETS={1}
.PHONY: all clean veryclean
all:
$(NINJA)
$(TARGETS):
$(NINJA) $(PWD)/$@
clean:
$(NINJA) -t clean
veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90.make irpf90_entities dist tags
""".format(irpdir, targets)
import makefile
with open(makefile.IRPF90_MAKE,'w') as file:
file.write(result)
def run():
output = [ "builddir = %s"%os.path.join(cwd,irpdir) ]
# Environment variables
try: FC = os.environ["FC"]
except KeyError: FC="gfortran -ffree-line-length-none"
try: AR = os.environ["AR"]
except KeyError: AR="ar"
try: CC = os.environ["CC"]
except KeyError: CC="gcc"
try: CXX = os.environ["CXX"]
except KeyError: CXX="g++"
includes = [ "-I %s"%(i) for i in command_line.include_dir ]
FC += " "+' '.join(includes)
CC += " "+' '.join(includes)
CXX += " "+' '.join(includes)
try: SRC = os.environ["SRC"].split()
except KeyError: SRC=[]
try: OBJ = os.environ["OBJ"].split()
except KeyError: OBJ=[]
try: LIB = os.environ["LIB"].split()
except KeyError: LIB=[]
try: FCFLAGS = os.environ["FCFLAGS"].split()
except KeyError: FCFLAGS = [ "-O2" ]
try: CFLAGS = os.environ["CFLAGS"].split()
except KeyError: CFLAGS = [ "-O2" ]
try: CXXFLAGS = os.environ["CXXFLAGS"].split()
except KeyError: CXXFLAGS = [ "-O2" ]
FCFLAGS = ' '.join(FCFLAGS)
CFLAGS = ' '.join(CFLAGS)
CXXFLAGS = ' '.join(CXXFLAGS)
LIB = ' '.join(LIB)
# Rules
t = [ "rule compile_fortran_{id}",
" command = {FC} {FCFLAGS} -c $in -o $out",
" description = F : $short_in -> $short_out",
"",
"rule compile_touches_{id}",
" command = {FC} -c $in -o $out",
" description = F : $short_in -> $short_out",
"",
"",
"rule compile_c_{id}" ,
" command = {CC} {CFLAGS} -c $in -o $out",
" description = C : $short_in -> $short_out",
"",
"rule compile_cxx_{id}",
" command = {CXX} {CXXFLAGS} -c $in -o $out",
" description = C++ : $short_in -> $short_out",
"",
"rule link_lib_{id}",
" command = {AR} crf $out $in" ,
" description = Link: $short_out",
"",
"rule link_{id}",
" command = {FC} $in {LIB} -o $out" ,
" description = Link: $short_out"]
output += [ '\n'.join(t).format(id=irp_id, FC=FC, FCFLAGS=FCFLAGS, LIB=LIB, CXX=CXX, CXXFLAGS=CXXFLAGS, CC=CC, CFLAGS=CFLAGS, AR=AR) ]
# All modules : list of Fmodule objects
l_mod = list( modules.values() )
# Modules that are not targets
l_non_targets = [ x for x in l_mod if not x.is_main ]
# Common object/source files
l_common_o = [ "irp_touches.irp.o" ] + \
[ "{0}.irp.o".format(x.filename) for x in l_non_targets ] + \
[ "{0}.irp.module.o".format(x.filename) for x in l_non_targets ]
l_common_s = []
if command_line.do_assert:
l_common_o += [ "irp_stack.irp.o" ]
l_common_s += [ "irp_stack.irp.F90" ]
if command_line.do_openmp:
l_common_o += [ "irp_locks.irp.o" ]
l_common_s += [ "irp_locks.irp.F90" ]
if command_line.do_profile:
l_common_o += [ "irp_profile.irp.o", "irp_rdtsc.o" ]
l_common_s += [ "irp_profile.irp.F90", "irp_rdtsc.c" ]
l_common_o = map(dress,l_common_o) + map(lambda x: dress(x,in_root=True), OBJ)
l_common_s = map(dress,l_common_s) + map(lambda x: dress(x,in_root=True), SRC)
# IRP_touches
output.append(create_build_touches(l_common_o[1:]))
# All targets : list of Fmodule objects
l_targets = [ x for x in l_mod if x.is_main ]
# Create lines
for i in l_non_targets:
output.append (create_build_non_target(i,OBJ))
for i in l_targets:
output.append(create_build_target(i, l_common_o))
# Remaining files
for i in l_common_s:
output.append(create_build_remaining(i))
with open(FILENAME,'w') as f:
f.write('\n\n'.join(output))
f.write('\n')
create_irpf90_make([ x.filename for x in l_targets ] + [ os.path.join(irpdir,'irpf90.a') ] )
return

View File

@ -24,46 +24,23 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
from util import * from util import *
from irpf90_t import * from irpf90_t import *
from variables import variables
from preprocessed_text import preprocessed_text
from subroutines import subroutines
import regexps, re import regexps, re
import error
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)
re_string_sub = regexps.re_string.sub re_string_sub = regexps.re_string.sub
regexps_re_string_sub = regexps.re_string.sub regexps_re_string_sub = regexps.re_string.sub
def find_variables_in_line(line):
assert isinstance(line,Line)
result = []
sub_done = False
buffer = line.lower
ap = result.append
for v,same_as,regexp in vtuple:
if v in buffer:
if not sub_done:
buffer = regexps_re_string_sub('',buffer)
sub_done = True
if regexp.search(buffer) is not None:
ap(same_as)
return result
def find_funcs_in_line(line):
def find_variables_in_line(line, vtuple):
line_lower = regexps_re_string_sub('', line.lower)
return [same_as for v, same_as, regexp in vtuple if v in line_lower and regexp(line_lower)]
def find_funcs_in_line(line, stuple):
assert isinstance(line, Line) assert isinstance(line, Line)
result = [] line_lower = line.lower
append = result.append result = [s for s, regexp in stuple if s in line_lower and regexp.search(line_lower)]
sub_done = False
buffer = line.lower
for s,regexp in stuple:
if s in buffer:
if regexp.search(buffer) is not None:
append(s)
return result return result
@ -73,13 +50,15 @@ def find_subroutine_in_line(line):
buffer = buffer.split()[1].lower() buffer = buffer.split()[1].lower()
return buffer return buffer
def check_touch(line,vars,main_vars):
def check_touch(variables, line, vars, main_vars):
def fun(main_var): def fun(main_var):
if main_var not in variables: if main_var not in variables:
error.fail(line, "Variable %s unknown" % (main_var, )) error.fail(line, "Variable %s unknown" % (main_var, ))
x = variables[main_var] x = variables[main_var]
return [main_var]+x.others return [main_var] + x.others_entity_name
all_others = make_single(flatten( map(fun,main_vars) ))
all_others = uniquify(flatten(map(fun, main_vars)))
all_others.sort() all_others.sort()
vars.sort() vars.sort()
for x, y in zip(vars, all_others): for x, y in zip(vars, all_others):
@ -88,244 +67,272 @@ def check_touch(line,vars,main_vars):
message = "\n".join([message] + map(lambda x: "- %s" % (x, ), all_others)) message = "\n".join([message] + map(lambda x: "- %s" % (x, ), all_others))
error.fail(line, message) error.fail(line, message)
################################################################################
def update_variables():
for filename,text in preprocessed_text:
for line in filter(lambda x: type(x) in [ Touch, SoftTouch ], text): from collections import namedtuple
vars = line.lower.split() Parsed_text = namedtuple('Parsed_text', ['varlist', 'line'])
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
for line in filter(lambda x: type(x) == Free,text):
vars = line.lower.split()
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
for line in filter(lambda x: type(x) == Irp_read,text):
variables[line.filename]._is_read = True
for line in filter(lambda x: type (x) == Irp_write,text):
variables[line.filename]._is_written = True
################################################################################ ################################################################################
def get_parsed_text(filename, text, variables, subroutines, vtuple):
def get_parsed_text():
def func(filename, text):
varlist = [] varlist = []
result = [] result = []
append = result.append append = result.append
for line in text: #filter(
# lambda x: type(x) not in [ Doc, Begin_doc, End_doc ], for i, line in enumerate(text):
# text):
if type(line) in [ \ tmp_result = []
Empty_line, if isinstance(line,
Continue, (Empty_line, Continue, Return, Begin_shell, End_shell, Openmp, Directive, Use,
Return, Enddo, End_select, Endif, End, Implicit, Program, Subroutine, Function)):
Begin_shell,
End_shell, append(Parsed_text([], line))
Openmp,
Directive, elif isinstance(line, (Begin_provider, Cont_provider)):
Use,
Enddo, if isinstance(line, (Begin_provider)):
End_select,
Endif,
Implicit,
Program,
Subroutine,
Function,
End,
]:
append( ([],line) )
elif type(line) in [ Begin_provider, Cont_provider ]:
if type(line) == Begin_provider:
varlist = [] varlist = []
buffer = map(strip,line.lower.replace(']','').split(','))
assert len(buffer) > 1 v = line.lower.replace(']', '').split(',')[1].strip()
v = buffer[1]
varlist.append(v) varlist.append(v)
variable_list = find_variables_in_line(line)
try: variable_list = find_variables_in_line(line, vtuple)
variable_list.remove(variables[v].same_as) variable_list.remove(variables[v].same_as)
except ValueError:
print v, variables[v].same_as append(Parsed_text(variable_list, line))
raise
append( (variable_list,line) )
elif type(line) == End_provider: elif type(line) == End_provider:
varlist = [] varlist = []
append( ([],line) ) append(Parsed_text([], line))
elif type(line) == Provide: elif type(line) == Provide:
l = line.lower.split()[1:] l = line.lower.split()[1:]
l = filter(lambda x: x not in varlist, l) l = filter(lambda x: x not in varlist, l)
for v in l: for v in l:
if v not in variables: if v not in variables:
error.fail(line, "Variable %s is unknown" % (v)) 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)) ) append(Parsed_text(l, Provide(line.i, "", line.filename)))
append(Parsed_text(l, Simple_line(line.i, "!%s" % (line.text), line.filename)))
elif type(line) == NoDep: elif type(line) == NoDep:
l = line.lower.split()[1:] l = line.lower.split()[1:]
for v in l: for v in l:
if v not in variables: if v not in variables:
error.fail(line, "Variable %s is unknown" % (v)) error.fail(line, "Variable %s is unknown" % (v))
l = map(lambda x: "-%s" % (x), l) l = map(lambda x: "-%s" % (x), l)
append( (l,Simple_line(line.i,"!%s"%(line.text),line.filename)) ) append(Parsed_text(l, Simple_line(line.i, "!%s" % (line.text), line.filename)))
elif type(line) in [Touch, SoftTouch]: elif type(line) in [Touch, SoftTouch]:
vars = line.lower.split() vars = line.lower.split()
if len(vars) < 2: if len(vars) < 2:
error.fail(line, "Syntax error") error.fail(line, "Syntax error")
vars = vars[1:] vars = vars[1:]
def fun(x):
main = variables[x].same_as main_vars = uniquify([variables[x].same_as for x in vars])
return main
main_vars = make_single( map(fun, vars) ) check_touch(variables, line, vars, main_vars)
check_touch(line,vars,main_vars)
txt = " ".join(vars) txt = " ".join(vars)
append ( (vars,Simple_line(line.i,"!",line.filename)) ) append(Parsed_text(vars, Simple_line(line.i, "!", line.filename)))
append ( ([],Simple_line(line.i,"! >>> TOUCH %s"%(txt,),line.filename)) ) append(Parsed_text([], Simple_line(line.i, "! >>> TOUCH %s" % (txt, ), line.filename)))
def fun(x): def fun(x):
if x not in variables: if x not in variables:
error.fail(line, "Variable %s unknown" % (x, )) error.fail(line, "Variable %s unknown" % (x, ))
return [ ([],Simple_line(line.i," call touch_%s"%(x,),line.filename)), return [
([],Use(line.i," use %s"%(variables[x].fmodule), line.filename)) ] Parsed_text([], Simple_line(line.i, " call touch_%s" % (x, ), line.filename)),
Parsed_text([], Use(line.i, " use %s" % (variables[x].fmodule), line.filename))
]
result += flatten(map(fun, main_vars)) result += flatten(map(fun, main_vars))
def fun(x): def fun(x):
if x not in variables: if x not in variables:
error.fail(line, "Variable %s unknown" % (x, )) error.fail(line, "Variable %s unknown" % (x, ))
return ([],Simple_line(line.i," %s_is_built = .True."%(x,),line.filename)) return Parsed_text(
[], Simple_line(line.i, " %s_is_built = .True." % (x, ), line.filename))
result += map(fun, main_vars[:-1]) result += map(fun, main_vars[:-1])
if type(line) == SoftTouch: if type(line) == SoftTouch:
append ( ([],Simple_line(line.i,"! <<< END TOUCH (Soft)",line.filename)) ) append(
Parsed_text([], Simple_line(line.i, "! <<< END TOUCH (Soft)", line.filename)))
else: else:
append ( ([],Provide_all(line.i,"! <<< END TOUCH",line.filename)) ) append(Parsed_text([], Provide_all(line.i, "! <<< END TOUCH", line.filename)))
elif type(line) == Call: elif type(line) == Call:
l = find_variables_in_line(line) l = find_variables_in_line(line, vtuple)
l = filter(lambda x: x not in varlist, l) l = filter(lambda x: x not in varlist, l)
sub = find_subroutine_in_line(line) sub = find_subroutine_in_line(line)
if sub not in subroutines: if sub not in subroutines:
t = Simple_line t = Simple_line
append( (l,Simple_line(line.i,line.text,line.filename)) ) append(Parsed_text(l, Simple_line(line.i, line.text, line.filename)))
else: else:
append((l, line)) append((l, line))
if subroutines[sub].touches != []: if subroutines[sub].touches != []:
append( ([],Provide_all(line.i,"",line.filename)) ) append(Parsed_text([], Provide_all(line.i, "", line.filename)))
elif type(line) == Free: elif type(line) == Free:
vars = line.lower.split() vars = line.lower.split()
vars = vars[1:] vars = vars[1:]
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) ) append(Parsed_text([], Simple_line(line.i, "!%s" % (line.text), line.filename)))
use = map(lambda x: " use %s" % (variables[x].fmodule), vars) use = map(lambda x: " use %s" % (variables[x].fmodule), vars)
for var in vars: for var in vars:
result += map(lambda x: ([],Use(line.i,x,line.filename)), result += map(lambda x: Parsed_text([], Use(line.i, x, line.filename)),
make_single(use)) uniquify(use))
result += map(lambda x: ([],Simple_line(line.i,x,line.filename)), result += map(lambda x: Parsed_text([], Simple_line(line.i, x, line.filename)),
variables[var].free) variables[var].free)
elif type(line) == Irp_read: elif type(line) == Irp_read:
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) ) append(Parsed_text([], Simple_line(line.i, "!%s" % (line.text), line.filename)))
elif type(line) == Irp_write: elif type(line) == Irp_write:
append( ([],Simple_line(line.i,"!%s"%(line.text),line.filename)) ) append(Parsed_text([], Simple_line(line.i, "!%s" % (line.text), line.filename)))
elif type(line) in [Begin_doc, End_doc, Doc]: elif type(line) in [Begin_doc, End_doc, Doc]:
pass pass
else: else:
l = find_variables_in_line(line) l = find_variables_in_line(line, vtuple)
l = filter(lambda x: x not in varlist, l) l = filter(lambda x: x not in varlist, l)
append( (l,line) ) append(Parsed_text(l, line))
return result
#main_result = []
#for filename,text in preprocessed_text:
# main_result.append( (filename, func(filename,text)) )
#return main_result
return parallel_loop(func,preprocessed_text)
update_variables()
parsed_text = get_parsed_text()
return (filename, result)
###################################################################### ######################################################################
def move_to_top_list(text, it):
# ( List[ List[Entity], Line], Iterator)
'''Move the all the element of List[ List[Entity], Line] of Line's Type containt in IT are the top of text.
def move_to_top(text,t): Note:
assert type(text) == list - The permutation neeed to be done following `it` order
assert t in [ NoDep, Declaration, Implicit, Use, Cont_provider ] - We can have `nested` subroutine / Function. (Because of interface)
- This function is called way to much. Is need to be efficient
- This function is Unpure
- One pass over `text`
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
elif type(line) == t:
if inside:
text.pop(i)
begin += 1
text.insert(begin,(vars,line))
return text NB:
- I am not really proud of the Sentinel value for the deleted,
but I waste already so much time on more cleaver but not working solution...
'''
result = [] assert set(it).issubset([NoDep, Declaration, Implicit, Use, Cont_provider])
for filename,text in parsed_text:
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
# ~ # ~ # ~
# G e t P e r m u t a t i o n
# ~ # ~ # ~
from collections import defaultdict
d_permutation = defaultdict(list)
# Type:List(begin, Line)
# We will insert the Line at begin position later on
l_begin = []
for i, (l_var, line) in enumerate(text):
t = type(line)
if t in [Begin_provider, Module,Program, Subroutine, Function]:
l_begin.append(i)
elif t in [End_provider, End]:
l_begin.pop()
elif l_begin and t in it:
d_permutation[t].append( (l_begin[-1], [l_var, line]) )
# Put the sentinel, will be deleted after the insertion
text[i] = None
# ~ # ~ # ~
# O r d e r t h e m
# ~ # ~ # ~
# We need to do the permutation in the correct order
d_insert = defaultdict(list)
for t in reversed(it):
for begin, tline in d_permutation[t]:
d_insert[begin].append(tline)
# ~ # ~ # ~
# D o t h e m
# ~ # ~ # ~
# Because idx are sorted, it's easy to do the insert part of the move
# Just pad each insert by the number of precedent insert
padding = 0
for idx in sorted(d_insert.keys()):
for tline in d_insert[idx]:
text.insert(idx + padding + 1, tline)
padding += 1
# Now do the Delete part of the move. Fortunatly we put a sentinel to know the line to delete
for i in reversed(xrange(len(text))):
if text[i] is None:
del text[i]
def move_interface(parsed_text,s_type=(Use,Implicit,Declaration,Subroutine,Function,Module)):
# ( List[ List[Entity], Line], Iterator)
'''Move everything containt into 'interface' below the first instance of s_type who preced it
Note:
= This function is unpur
'''
# Get the born of the interface
i_begin = [ i for i, (_, line) in enumerate(parsed_text) if isinstance(line,Interface) ]
i_end = [ i+1 for i, (_, line) in enumerate(parsed_text) if isinstance(line,End_interface) ]
# Get the begin of the insert
i_insert = []
for begin in i_begin:
i_insert.append(next(i+1 for i in range(begin,-1,-1) if isinstance(parsed_text[i][1], s_type)))
# Do the insert and the delete in one passe
for insert, begin, end in zip(i_insert,i_begin,i_end):
parsed_text[insert:insert] = parsed_text[begin:end]
padding = end-begin
parsed_text[begin+padding:end+padding] = []
###################################################################### ######################################################################
def build_sub_needs(): def build_sub_needs(parsed_text, d_subroutine):
# Needs #(List[ Tuple[List[Entity], Tuple[int,List[Line]] ]], Dict[str:Sub]) -> None
for filename, text in parsed_text: '''Set the needs, and provides arguements of Routine present 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
sub._needs += vars
build_sub_needs() Note:
This function is unpure
'''
l_buffer = []
for _, text in parsed_text:
l_begin = [ i for i, (_, line) in enumerate(text) if isinstance(line, (Subroutine, Function, Program))]
l_end = [i for i, (_, line) in enumerate(text) if isinstance(line, End)]
l_buffer += [(d_subroutine[text[b].line.subname], text[b + 1:e]) for b, e in zip(l_begin, l_end) if not isinstance(text[b].line, Program)]
for sub, text in l_buffer:
sub.needs = set(v for vs, _ in text for v in vs)
sub.to_provide = set(v for vs, line in text for v in vs if isinstance(line, Declaration))
##################################################################### #####################################################################
def add_subroutine_needs():
def add_subroutine_needs(parsed_text, subroutines):
main_result = [] main_result = []
for filename, text in parsed_text: for filename, text in parsed_text:
result = [] result = []
append = result.append append = result.append
for vars, line in text: for vars, line in text:
if type(line) == Call: if type(line) == Call:
subname = find_subname(line) vars += subroutines[line.subname].to_provide
vars += subroutines[subname].to_provide
append((vars, line)) append((vars, line))
main_result.append((filename, result)) main_result.append((filename, result))
return main_result return main_result
parsed_text = add_subroutine_needs()
###################################################################### ######################################################################
def move_variables(): def move_variables(parsed_text):
#(List[ Tuple[List[Entity], Tuple[int,List[Line]] ]]
'''Move variables into the top of the declaraiton'''
def func(filename, text): def func(filename, text):
result = [] result = []
@ -339,8 +346,17 @@ def move_variables():
old_elsevars = [] old_elsevars = []
revtext = list(text) revtext = list(text)
revtext.reverse() revtext.reverse()
skip_interface = False
try: try:
for vars, line in revtext: for vars, line in revtext:
if type(line) in [Interface, End_interface]:
skip_interface = not skip_interface
if skip_interface:
append(([], line))
continue
if type(line) in [End_provider, End]: if type(line) in [End_provider, End]:
varlist = [] varlist = []
append(([], line)) append(([], line))
@ -383,7 +399,10 @@ def move_variables():
varlist += vars varlist += vars
append(([], line)) append(([], line))
except: except:
error.fail(line,"Unable to parse file") from util import logger
logger.error("Unable to parse file %s", line)
import sys
sys.exit(1)
result.reverse() result.reverse()
@ -395,20 +414,20 @@ def move_variables():
varlist = [] varlist = []
try: try:
for vars, line in text: for vars, line in text:
if vars != []: if vars:
vars = make_single(vars) vars = uniquify(vars)
if type(line) in [Begin_provider, Program, Subroutine, Function]: if type(line) in [Begin_provider, Program, Subroutine, Function]:
varlist = list(vars) varlist = list(vars)
elif type(line) in [If, Select]: elif type(line) in [If, Select]:
old_varlist.append(varlist) old_varlist.append(varlist)
vars = filter(lambda x: x not in varlist, vars) vars = filter(lambda x: x not in varlist, vars)
varlist = make_single(varlist + vars) varlist = uniquify(varlist + vars)
assert old_varlist is not varlist assert old_varlist is not varlist
elif type(line) in [Elseif, Else, Case]: elif type(line) in [Elseif, Else, Case]:
varlist = old_varlist.pop() varlist = old_varlist.pop()
old_varlist.append(varlist) old_varlist.append(varlist)
vars = filter(lambda x: x not in varlist, vars) vars = filter(lambda x: x not in varlist, vars)
varlist = make_single(varlist + vars) varlist = uniquify(varlist + vars)
assert old_varlist is not varlist assert old_varlist is not varlist
elif type(line) in [Endif, End_select]: elif type(line) in [Endif, End_select]:
varlist = old_varlist.pop() varlist = old_varlist.pop()
@ -430,78 +449,74 @@ def move_variables():
for filename, text in parsed_text: for filename, text in parsed_text:
main_result.append((filename, func(filename, text))) main_result.append((filename, func(filename, text)))
return main_result return main_result
#return parallel_loop(func,parsed_text)
parsed_text = move_variables()
###################################################################### ######################################################################
def build_needs(): def build_needs(parsed_text, subroutines, stuple, variables):
# Needs 'out: variable'
# ~#~#~#~#~#
# Needs and to_provide
# ~#~#~#~#~#
for filename, text in parsed_text: for filename, text in parsed_text:
var = None
for vars,line in text: l_begin = [i for i, (_, line) in enumerate(text) if isinstance(line, Begin_provider)]
if type(line) == Begin_provider: l_end = [i for i, (_, line) in enumerate(text) if isinstance(line, End_provider)]
buffer = map(strip,line.lower.replace(']',',').split(','))
var = variables[buffer[1]] for start, end in zip(l_begin, l_end):
var.needs = [] l_vars_start, line_start = text[start]
var.to_provide = vars
elif type(line) == End_provider: name = map(str.strip, line_start.lower.replace(']', ',').split(','))[1]
var.needs = make_single(var.needs) entity = variables[name]
var.to_provide = make_single(var.to_provide)
var = None entity.to_provide = uniquify(l_vars_start)
if var is not None:
var.needs += vars l_needs = []
for vars, line in text[start:end]:
l_needs += vars
if type(line) == Call: if type(line) == Call:
subname = find_subname(line) l_needs += subroutines[line.subname].needs
var.needs += subroutines[subname].needs elif type(line) in [Simple_line, Assert, Do, If, Elseif, Select]:
elif type(line) in [ \ funcs = find_funcs_in_line(line, stuple)
Simple_line, Assert,
Do , If,
Elseif , Select,
]:
funcs = find_funcs_in_line(line)
for f in funcs: for f in funcs:
var.needs += subroutines[f].needs l_needs += subroutines[f].needs
entity.needs = uniquify(l_needs)
for v in variables: for v in variables:
main = variables[v].same_as main = variables[v].same_as
if main != v: if main != v:
variables[v].needs = variables[main].needs variables[v].needs = variables[main].needs
variables[v].to_provide = variables[main].to_provide variables[v].to_provide = variables[main].to_provide
# Needed_by # ~#~#~#~#~#
# Needs and to_provide
# ~#~#~#~#~#
for v in variables: for v in variables:
variables[v].needed_by = [] variables[v].needed_by = []
for v in variables: for v in variables:
main = variables[v].same_as main = variables[v].same_as
if main != v: if main != v:
variables[v].needed_by = variables[main].needed_by variables[v].needed_by = variables[main].needed_by
for v in variables: for v in variables:
var = variables[v] var = variables[v]
if var.is_main: if var.is_main:
for x in var.needs: for x in var.needs:
variables[x].needed_by.append(var.same_as) variables[x].needed_by.append(var.same_as)
for v in variables: for v in variables:
var = variables[v] var = variables[v]
var.needed_by = make_single(var.needed_by) var.needed_by = uniquify(var.needed_by)
build_needs()
result = []
for filename,text in parsed_text:
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
###################################################################### ######################################################################
from command_line import command_line from command_line import command_line
def check_opt():
def check_opt(parsed_text):
if not command_line.do_checkopt: if not command_line.do_checkopt:
return return
@ -517,10 +532,10 @@ def check_opt():
do_level += 1 do_level += 1
elif type(line) == Enddo: elif type(line) == Enddo:
do_level -= 1 do_level -= 1
check_opt()
###################################################################### ######################################################################
def perform_loop_substitutions(): def perform_loop_substitutions(parsed_text):
main_result = [] main_result = []
for filename, text in parsed_text: for filename, text in parsed_text:
result = [] result = []
@ -535,15 +550,3 @@ def perform_loop_substitutions():
main_result.append((filename, result)) main_result.append((filename, result))
return main_result return main_result
parsed_text = perform_loop_substitutions()
######################################################################
if __name__ == '__main__':
for i in range(len(parsed_text)):
if parsed_text[i][0] == sys.argv[1]:
print '!-------- %s -----------'%(parsed_text[i][0])
for line in parsed_text[i][1]:
print line[1]
print line[0], line[1].filename
#for i in subroutines:
# print i, subroutines[i].needs, subroutines[i].to_provide

View File

@ -26,18 +26,20 @@
from irpf90_t import * from irpf90_t import *
from regexps import * from regexps import *
import error
from command_line import command_line from command_line import command_line
from util import * from util import *
import sys
# Local regular expressions # Local regular expressions
re_endif = re.compile("end\s+if") re_endif = re.compile("end +if")
re_elseif = re.compile("else\s+if") re_elseif = re.compile("else +if")
re_enddo = re.compile("end\s+do") re_enddo = re.compile("end +do")
re_endtype= re.compile("end\s+type") re_endwhere = re.compile("end +where")
re_endmodule = re.compile("end\s+module")
re_endselect = re.compile("end\s+select") re_endtype = re.compile("end +type.*")
re_endinterface = re.compile("end\s+interface") re_endmodule = re.compile("end +module",re.I)
re_endselect = re.compile("end +select")
re_endinterface = re.compile("end +interface")
# Local variables # Local variables
Free_form = 0 Free_form = 0
@ -86,54 +88,52 @@ simple_dict = {
"save": Declaration, "save": Declaration,
"function": Function, "function": Function,
"recursive": Function, "recursive": Function,
"select": Select,
"selectcase": Select,
"module": Module,
"endmodule": End_module,
"interface": Interface,
"endinterface": End_interface,
"where": Where,
"elsewhere": Elsewhere,
"endwhere": Endwhere,
} }
def get_type (i, filename, line, is_doc): def get_canonized_text(text_lower):
'''Find the type of a text line'''
assert type(i) == int
assert type(filename) == str
assert type(line) == str
assert type(is_doc) == bool
# add support for interface block text_canonized = text_lower
has_interface = False text_canonized = re_elseif.sub("elseif", text_canonized)
text_canonized = re_enddo.sub("enddo", text_canonized)
line = line.rstrip() text_canonized = re_endtype.sub("endtype", text_canonized)
line = line.replace("$IRP_ALIGN",command_line.align) text_canonized = re_endmodule.sub("endmodule", text_canonized)
lower_line0 = line.lstrip().lower() text_canonized = re_endif.sub("endif", text_canonized)
lower_line = lower_line0.replace("!"," ! ") text_canonized = re_endselect.sub("endselect", text_canonized)
text_canonized = re_endinterface.sub("endinterface", text_canonized)
# Replacements text_canonized = re_endwhere.sub('endwhere',text_canonized)
lower_line = re_elseif.sub("elseif",lower_line)
lower_line = re_enddo.sub("enddo",lower_line)
lower_line = re_endtype.sub("endtype",lower_line)
lower_line = re_endmodule.sub("endmodule",lower_line)
lower_line = re_endif.sub("endif",lower_line)
lower_line = re_endselect.sub("endselect",lower_line)
lower_line = re_endinterface.sub("endinterface",lower_line)
for c in """()'"[]""": for c in """()'"[]""":
lower_line = lower_line.replace(c," "+c+" ") text_canonized = text_canonized.replace(c, " %s " % c)
return text_canonized
buffer = lower_line.split()
if len(buffer) == 0: def get_type(i, filename, line, line_lower, line_lower_canonized, is_doc):
# ( int,str,str,str,str,bool) -> Irpf90_t
'''Find the type of a text line'''
line = line.rstrip()
l_word = line_lower_canonized.split()
if not l_word:
return [Empty_line(i, line, filename)], is_doc return [Empty_line(i, line, filename)], is_doc
firstword = buffer[0] # Handle archaic do loop of f77
firstword = l_word[0]
if firstword.isdigit(): if firstword.isdigit():
assert len(buffer) > 1 l_word = l_word[1:]
buffer = buffer[1:] firstword = l_word[0]
firstword = buffer[0]
# Identify line
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
if firstword == "contains":
return [Contains(i, line, filename)], False
if firstword == "end_doc": if firstword == "end_doc":
return [End_doc(i, line, filename)], False return [End_doc(i, line, filename)], False
@ -144,116 +144,145 @@ def get_type (i, filename, line, is_doc):
return [Doc(i, line, filename)], is_doc return [Doc(i, line, filename)], is_doc
if firstword in simple_dict: if firstword in simple_dict:
return [ simple_dict[firstword](i,line,filename) ], is_doc type_ = simple_dict[firstword]
return [type_(i, line, filename)], is_doc
if firstword in [ "select", "selectcase" ]:
return [ Select(i,line,filename) ] , is_doc
if len(lower_line0) > 4: #label do-loop (outer: do i=1,sze)
reg_do_lab = ur":\s+do\s+"
if re.search(reg_do_lab,line_lower):
return [Do(i,line,filename)], is_doc
if firstword[0] == '#':
lower_line = line_lower.strip()[1:]
if len(lower_line) <= 3:
return [Simple_line(i, line, filename)], is_doc
#WARNING: The regex shloud match endtype. Don't know why it's not the case
if re_decl.match(line_lower_canonized) or line_lower_canonized == 'endtype':
if "function" in l_word[1:3]:
return [Function(i, line, filename)], is_doc
else:
return [Declaration(i, line, filename)], is_doc
if firstword.startswith('#'):
result = [Simple_line(i, line, filename)] result = [Simple_line(i, line, filename)]
error.warn ( result[0] ,
"""irpf90 may not work with preprocessor directives. You can use logger.info("%s:"
Irp_if ... Irp_else ... Irp_endif "irpf90 may not work with preprocessor directives. You can use"
instead of "Irp_if ... Irp_else ... Irp_endif"
#ifdef ... #else ... #endif""" ) "instead of"
"#ifdef ... #else ... #endif"%line)
return result, is_doc return result, is_doc
if firstword.startswith("case("): if firstword.startswith("case("):
return [Case(i, line, filename)], is_doc return [Case(i, line, filename)], is_doc
if lower_line0[1:5] == "$omp": if lower_line.startswith("$omp"):
return [Openmp(i, line, filename)], is_doc return [Openmp(i, line, filename)], is_doc
elif lower_line0[1:5] in ["dec$", "dir$"] and command_line.directives: if lower_line.startswith(("dec$", "dir$")) and command_line.directives:
return [Directive(i, line, filename)], is_doc return [Directive(i, line, filename)], is_doc
elif lower_line0[1:3] == "$ ": if lower_line.startswith("$ "):
return [Openmp(i, line, filename)], is_doc return [Openmp(i, line, filename)], is_doc
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
# Detect errors # Detect errors
if firstword == "dowhile": if firstword == "dowhile":
error.fail( Do(i,line,filename) , "'do while' should be in 2 words." ) logger.error("%s 'do while' should be in 2 words." % Do(i, line, filename))
sys.exit(1)
return [Simple_line(i, line, filename)], is_doc return [Simple_line(i, line, filename)], is_doc
###################################################################### ######################################################################
def get_text(lines,filename): import os.path
'''Read the input file and transform it to labeled lines'''
assert type(filename) == str
assert type(lines) == list
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 save_and_execute(irpdir, scriptname, code, interpreter):
def execute_shell(text): # (str, str, List, str) -> List[Line]
'''Execute the embedded shell scripts''' ''' Save the script in irpdir/scriptname and Execute it
def fail(l,a,b): error.fail(l,"In Begin_Shell, %s '%s'"%(a,b))
inside = False Note:
result = [] The script are executed in the orginal directory of the .irp.f (aka '..')
for line in text: and this directory is added to PYTHONPATH.
if inside: '''
if type(line) == Begin_shell:
error.fail(line,"Nested Begin_shell") irpdir_scriptname = os.path.abspath(os.path.join(irpdir, scriptname))
elif type(line) == End_shell: with open(irpdir_scriptname, 'w') as f:
inside = False f.writelines(code)
# Write script file
scriptname = "%s%s_shell_%d"%(irpdir,line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
scriptname = "%s_shell_%d"%(line.filename,line.i)
file = open(scriptname,'w')
file.writelines(script)
file.close()
# Execute shell # Execute shell
import os import util
pipe = os.popen("%s < %s"%(shell,scriptname),'r') try:
lines = pipe.readlines() text = util.check_output('PYTHONPATH=$PYTHONPATH:. %s %s' % (interpreter, irpdir_scriptname), shell=True, bufsize=-1, cwd=os.path.join(irpdir,'..'))
pipe.close() except:
result += get_text(lines,scriptname) util.logger.error("Something wrong append with embeded '%s' script: %s"% (interpreter, irpdir_scriptname))
os.remove(scriptname) import sys
sys.exit(1)
# Create the Line
p = Preprocess_text(scriptname)
p.text = text
return p.lines_overloaded
#######################################################################
def execute_shell(text):
# (List[Line]) -> List[Line]
'''Execute the embedded shell scripts'''
l_begin = [i for i,line in enumerate(text) if isinstance(line,Begin_shell)]
l_end = [i for i,line in enumerate(text) if isinstance(line,End_shell)]
l_output= []
# ~=~=~=~
# E x e c u t e S h e l l
# ~=~=~=~
from util import logger
import sys
def fail(l, a, b):
logger.error("%s In Begin_Shell, %s '%s'" % (l,a, b))
sys.exit(1)
for begin,end in zip(l_begin,l_end):
header = text[begin]
header_text = header.text
for bracket in ['[', ']']:
n = header_text.count(bracket)
assert n <= 1, fail(header_text, "Too many", bracket)
assert n >= 1, fail(header_text, "Missing", bracket)
else: else:
script.append(line.text+'\n') interpreter = header_text[header_text.find('[')+1: header_text.find(']')].strip()
else: script = ['%s\n' % l.text for l in text[begin+1:end] ]
if type(line) == Begin_shell: scriptname="%s_shell_%d" % (header.filename, header.i)
inside = True
begin = line.i l_output.append(save_and_execute(irpdir, scriptname, script,interpreter))
script = []
# Find shell executable # ~=~=~=~
buffer = line.text.split('[') # R e p l a c e
if len(buffer) > 2: # ~=~=~=~
fail(line,"Too many",'[')
elif len(buffer) < 2: #Deep copy for pure function
fail(line,"Missing",'[') text_new = text[:]
buffer = buffer[1]
buffer = buffer.split(']') # Because we use slicing and we want to include the end line
if len(buffer) > 2: l_end_include = [i+1 for i in l_end]
fail(line,"Too many",']') padding = 0
elif len(buffer) < 2: for begin,end, out in zip(l_begin,l_end_include,l_output):
fail(line,"Missing",']') text_new[begin+padding:end+padding] = out
shell = buffer[0].strip() padding += len(out) - (end-begin)
elif type(line) == End_shell:
error.fail(line,"Begin_shell missing") return text_new
else:
result.append(line)
return result
###################################################################### ######################################################################
def execute_templates(text): def execute_templates(text):
'''Execute the templates''' '''Execute the templates'''
def fail(l,a,b): error.fail(l,"In %s, %s"%(a,b))
def fail(l, a, b):
error.fail(l, "In %s, %s" % (a, b))
def get_variables(line): def get_variables(line):
buffer = line.text.split('[', 1) buffer = line.text.split('[', 1)
@ -301,7 +330,8 @@ def execute_templates(text):
for s in subst.split(';;'): for s in subst.split(';;'):
buffer = map(lambda x: x.strip(), s.split(';')) buffer = map(lambda x: x.strip(), s.split(';'))
if len(buffer) != len(variables): if len(buffer) != len(variables):
fail(line,"subst","%d variables defined, and %d substitutions"%(len(variables),len(buffer))) fail(line, "subst", "%d variables defined, and %d substitutions" %
(len(variables), len(buffer)))
script += "v.append( { \\\n" script += "v.append( { \\\n"
for t, v in zip(variables, buffer): for t, v in zip(variables, buffer):
script += ' "%s": """%s""" ,\n' % (t, v) script += ' "%s": """%s""" ,\n' % (t, v)
@ -310,27 +340,13 @@ def execute_templates(text):
for v in variables: for v in variables:
script += " t0 = t0.replace('%s',d['%s'])\n" % (v, v) script += " t0 = t0.replace('%s',d['%s'])\n" % (v, v)
script += " print t0\n" script += " print t0\n"
# Write script file result += save_and_execute(irpdir, scriptname="%s_template_%d" % (line.filename, line.i), code=script,interpreter="python")
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
pipe = os.popen("python < %s"%(scriptname),'r')
lines = pipe.readlines()
pipe.close()
result += get_text(lines,scriptname)
os.remove(scriptname)
else: else:
subst += line.text + '\n' subst += line.text + '\n'
return result return result
###################################################################### ######################################################################
def form(text): def form(text):
'''Find if the text is in fixed form or in free form''' '''Find if the text is in fixed form or in free form'''
@ -350,13 +366,13 @@ def form(text):
if test[0] in "Cc#!*": if test[0] in "Cc#!*":
pass pass
else: else:
if re2.match(test) is None and \ if re2.match(test) is None and re3.match(test) is not None:
re3.match(test) is not None:
return Free_form return Free_form
if line.text.rstrip()[-1] == '&': if line.text.rstrip()[-1] == '&':
return Free_form return Free_form
return Fixed_form return Fixed_form
###################################################################### ######################################################################
def add_operators(text): def add_operators(text):
re_incr = re.compile(r"(\s*)(.*)(\+=)(.*$)", re.S) re_incr = re.compile(r"(\s*)(.*)(\+=)(.*$)", re.S)
@ -384,17 +400,38 @@ def add_operators(text):
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def remove_comments(text, form): def remove_comments(text, form):
'''Remove all comments''' # (List[Line], int) -> List[Line]
'''Remove all comments
Note:
This function is unpur
'''
result = [] result = []
def remove_after_bang(line): def remove_after_bang(str_):
match = re_comment.match(line) # str -> str
if match is None: i_bang = str_.find('!')
return line
if i_bang == -1:
return str_
else: else:
return re_comment.split(line)[1].rstrip() sentinel, inside = None, False
for i,c in enumerate(str_):
if c == '"' or c == "'":
if not inside:
inside = True
sentinel = c
elif sentinel == c:
inside = False
elif c == '!' and not inside:
return str_[:i].strip()
return str_
if form == Free_form: if form == Free_form:
for line in text: for line in text:
@ -404,11 +441,12 @@ def remove_comments(text,form):
pass pass
else: else:
newline = line.text.lstrip() newline = line.text.lstrip()
if newline == "" or newline[0] == "!": if (newline != "" and newline[0] != "!#"):
pass text = remove_after_bang(line.text)
else: if text:
line.text = remove_after_bang(line.text) line.text = text
result.append(line) result.append(line)
return result return result
else: else:
for line in text: for line in text:
@ -426,6 +464,7 @@ def remove_comments(text,form):
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def remove_continuation(text, form): def remove_continuation(text, form):
'''Removes continuation lines''' '''Removes continuation lines'''
@ -472,6 +511,7 @@ def irp_simple_statements(text):
'''Processes simple statements''' '''Processes simple statements'''
def process_irp_rw(line, rw, t): def process_irp_rw(line, rw, t):
'''Read Write'''
assert type(line) == t assert type(line) == t
buffer = line.text.split() buffer = line.text.split()
if len(buffer) == 2: if len(buffer) == 2:
@ -487,7 +527,7 @@ def irp_simple_statements(text):
txt = line.text.lstrip() txt = line.text.lstrip()
result = [ result = [
Empty_line(i, "!", f), Empty_line(i, "!", f),
t(i,"! >>> %s"%(txt,),variable ), t(i, "! >>> %s" % txt, variable),
Provide_all(i, " call %ser_%s('%s')" % (rw, variable, num), f), Provide_all(i, " call %ser_%s('%s')" % (rw, variable, num), f),
Empty_line(i, "! >>> END %s " % (txt, ), f), Empty_line(i, "! >>> END %s " % (txt, ), f),
Empty_line(line.i, "!", f), Empty_line(line.i, "!", f),
@ -524,7 +564,8 @@ def irp_simple_statements(text):
ok = ok and "'" not in m # not a string ok = ok and "'" not in m # not a string
ok = ok and m.count('(') == m.count(')') # balanced parenthesis ok = ok and m.count('(') == m.count(')') # balanced parenthesis
if ok: if ok:
result.append ( Simple_line (line.i, " print *, '%s = ', %s"%(m,m), line.filename) ) result.append(
Simple_line(line.i, " print *, '%s = ', %s" % (m, m), line.filename))
result.append(Simple_line(line.i, " print *, ''", line.filename)) result.append(Simple_line(line.i, " print *, ''", line.filename))
return result return result
@ -549,89 +590,79 @@ def irp_simple_statements(text):
Simple_line(i, " print *, ' file: %s, line: %d'" % (f, i), f), Simple_line(i, " print *, ' file: %s, line: %d'" % (f, i), f),
Simple_line(i, " print *, '%s'" % (condition_str, ), f), Simple_line(i, " print *, '%s'" % (condition_str, ), f),
] + debug_conditions(line) + [ ] + debug_conditions(line) + [
Simple_line(i, " stop 1", f), Simple_line(i, " stop 1", f), Endif(i, " endif", f), Empty_line(
Endif (i, " endif", f), i, "! <<< END %s" % (txt, ), f), Empty_line(i, "!", f)
Empty_line(i, "! <<< END %s"%(txt,), f),
Empty_line(i, "!", f)
] ]
else: else:
result = [] result = []
return result return result
def process_end(line): def process_end(line):
'''Set irp_here variable in provider block''' '''Add irp_leave if necessary'''
line.text = "end"
if command_line.do_assert or command_line.do_debug: if command_line.do_assert or command_line.do_debug:
i = line.i i = line.i
f = line.filename f = line.filename
result = [ result = [Simple_line(i, " call irp_leave(irp_here)", f), line]
Simple_line(i," call irp_leave(irp_here)", f),
line
]
else: else:
result = [line] result = [line]
return result return result
def process_begin_provider(line): def process_begin_provider(line):
assert type(line) == Begin_provider assert type(line) == Begin_provider
buffer = line.lower.replace('['," ") import string
buffer = buffer.replace(']',"") trans = string.maketrans("[]"," ")
buffer = buffer.split(',') buffer = line.lower.translate(trans).split(',')
if len(buffer) < 2: if len(buffer) < 2:
error.fail(line, "Error in Begin_provider statement") error.fail(line, "Error in Begin_provider statement")
varname = buffer[1].strip() varname = buffer[1].strip()
length = len(varname) length = len(varname)
i = line.i i = line.i
f = line.filename f = line.filename
result = [ Begin_provider(i,line.text, (f,varname)), result = [
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,varname), f) ] Begin_provider(i, line.text, (f, varname)),
if command_line.do_assert or command_line.do_debug: Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, varname), f)
result += [
Simple_line(i," call irp_enter(irp_here)", f),
] ]
if command_line.do_assert or command_line.do_debug:
result += [Simple_line(i, " call irp_enter(irp_here)", f), ]
return result return result
def process_cont_provider(line): def process_cont_provider(line):
assert type(line) == Cont_provider assert type(line) == Cont_provider
buffer = line.lower.replace('['," ") buf = line.lower.replace('[', " ").replace(']', "").split(',')
buffer = buffer.replace(']',"") if len(buf) < 2:
buffer = buffer.split(',')
if len(buffer) < 2:
error.fail(line, "Error in Cont_provider statement") error.fail(line, "Error in Cont_provider statement")
varname = buffer[1].strip() varname = buf[1].strip()
i = line.i i = line.i
f = line.filename f = line.filename
return [Cont_provider(i, line.text, (f, varname))] return [Cont_provider(i, line.text, (f, varname))]
def process_subroutine(line): def process_subroutine(line):
assert type(line) == Subroutine assert type(line) == Subroutine
subname = find_subname(line) subname = line.subname
length = len(subname) length = len(subname)
i = line.i i = line.i
f = line.filename f = line.filename
result = [ line, result = [ line, Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, subname), f)]
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,subname), f) ]
if command_line.do_assert or command_line.do_debug: if command_line.do_assert or command_line.do_debug:
result += [ result += [Simple_line(i, " call irp_enter_f(irp_here)", f), ]
Simple_line(i," call irp_enter_f(irp_here)", f),
]
return result return result
def process_function(line): def process_function(line):
assert type(line) == Function assert type(line) == Function
subname = find_subname(line) subname = line.subname
length = len(subname) length = len(subname)
i = line.i i = line.i
f = line.filename f = line.filename
result = [ line, result = [
Declaration(i," character*(%d) :: irp_here = '%s'"%(length,subname), f) ] line, Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, subname), f)
if command_line.do_assert or command_line.do_debug:
result += [
Simple_line(i," call irp_enter_f(irp_here)", f),
] ]
if command_line.do_assert or command_line.do_debug:
result += [Simple_line(i, " call irp_enter_f(irp_here)", f), ]
return result return result
def process_program(line): def process_program(line):
assert type(line) == Program assert type(line) == Program
program_name = line.lower.split()[1] program_name = line.lower.split()[1]
@ -643,13 +674,16 @@ def irp_simple_statements(text):
temp += [Call(0, " call %s" % (program_name), line.filename)] temp += [Call(0, " call %s" % (program_name), line.filename)]
if command_line.do_profile: if command_line.do_profile:
temp += [Simple_line(0, "call irp_print_timer()", line.filename)] temp += [Simple_line(0, "call irp_print_timer()", line.filename)]
temp += [Simple_line(0, " call irp_finalize_%s()" % (irp_id), line.filename)] temp += [Simple_line(0, " call irp_finalize_%s()" % (irp_id), line.filename)]
temp += [End(0, "end program", line.filename)] temp += [End(0, "end program", line.filename)]
result = temp + \
process_subroutine( Subroutine(line.i,"subroutine %s"%(program_name,),line.filename) ) result = temp + process_subroutine(
Subroutine(line.i, "subroutine %s" % (program_name, ), line.filename))
return result return result
d = { Irp_read : process_irp_read, d = {
Irp_read: process_irp_read,
Irp_write: process_irp_write, Irp_write: process_irp_write,
Return: process_return, Return: process_return,
Assert: process_assert, Assert: process_assert,
@ -662,6 +696,7 @@ def irp_simple_statements(text):
Program: process_program, Program: process_program,
} }
result = [] result = []
for line in text: for line in text:
buffer = [line] buffer = [line]
@ -670,6 +705,7 @@ def irp_simple_statements(text):
buffer = d[t](line) buffer = d[t](line)
break break
result += buffer result += buffer
return result return result
@ -681,7 +717,6 @@ def change_includes(text):
if type(line) == Include: if type(line) == Include:
txt = line.text.replace('"', "'").split("'") txt = line.text.replace('"', "'").split("'")
if len(txt) != 3: if len(txt) != 3:
print txt
error.fail(line, "Error in include statement") error.fail(line, "Error in include statement")
directory = (("./" + line.filename).rsplit('/', 1)[0] + '/')[2:] directory = (("./" + line.filename).rsplit('/', 1)[0] + '/')[2:]
if directory == "": if directory == "":
@ -689,30 +724,31 @@ def change_includes(text):
else: else:
filename = directory + txt[1].strip() filename = directory + txt[1].strip()
try: try:
file = open(filename,'r')
file.close()
result.append(Include(line.i, "! include '%s'" % filename, filename)) result.append(Include(line.i, "! include '%s'" % filename, filename))
result += create_preprocessed_text(filename) result += Preprocess_text(filename).preprocessed_text
except IOError: except IOError:
result.append(Declaration(line.i, line.text, line.filename)) result.append(Declaration(line.i, line.text, line.filename))
else: else:
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def process_old_style_do(text): def process_old_style_do(text):
'''Changes old-style do loops to new style''' # (List[Line]) -> List[Line]
assert type(text) == list '''Changes archaic do loops to new style
DO 1 i=1,10'''
def change_matching_enddo(begin, number): def change_matching_enddo(begin, number):
for i in range(begin+1,len(text)): for i,line in enumerate(text[begin+1:]):
line = text[i] if isinstance(line,(Continue,Enddo)) and line.text.split()[0] == number:
if type(line) in [Continue,Enddo]: text[begin+1+i] = Enddo(line.i, " enddo", line.filename)
buffer = line.text.split()
if buffer[0] == number:
text[i] = Enddo(line.i," enddo",line.filename)
return return
error.fail(text[begin],"Old-style do loops should end with 'continue' or 'end do'")
from util import logger
logger.error(text[begin], "(%s) Old-style do loops should end with 'continue' or 'end do'" % text[begin])
from util import sys
sys.exit(1)
result = [] result = []
for i in range(len(text)): for i in range(len(text)):
@ -729,18 +765,18 @@ def process_old_style_do(text):
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def change_single_line_ifs(text): def change_single_line_ifs(text):
'''Changes: # List[Line] -> List[Line]
if (test) result '''Changes: `if (test) result`
into
to `if (test) then
if (test) then
result result
endif''' endif`'''
regex = r"\(.*?\)"
assert type(text) == list
result = [] result = []
for line in text: for line in text:
if type(line) == If: if type(line) == If:
@ -749,8 +785,10 @@ endif'''
else: else:
buffer = line.text buffer = line.text
begin = buffer.find('(') begin = buffer.find('(')
if begin < 0: if begin == -1:
error.fail(line,"Error in if statement") logger.error("No '(' in if statemnt: %s" % line)
sys.exit(1)
level = 0 level = 0
instring = False instring = False
for i, c in enumerate(buffer[begin:]): for i, c in enumerate(buffer[begin:]):
@ -766,85 +804,68 @@ endif'''
end = begin + i + 1 end = begin + i + 1
break break
if level != 0: if level != 0:
error.fail(line,"Error in if statement") logger.error("If statement not valid: %s (%s)" % (line, line.filename))
sys.exit(1)
test = buffer[:end] test = buffer[:end]
code = buffer[end:] code = buffer[end:]
i = line.i i = line.i
f = line.filename f = line.filename
result.append(If(i, "%s then" % (test, ), f)) result.append(If(i, "%s then" % (test, ), f))
result += get_type(i,f,code,False)[0] result += get_type(i, f, code, code.lower(),code.lower(), False)[0]
result.append(Endif(i, " endif", f)) result.append(Endif(i, " endif", f))
else: else:
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def check_begin_end(text): def check_begin_end(raw_text):
'''Checks x...endx consistence''' # List[Line] -> None
'''Checks x...endx consistence
filter_line = lambda line: type(line) in [ Do, Enddo, If, Endif, \
Program, Begin_provider, End_provider, \
Subroutine, Function, End, Begin_doc, End_doc ]
text = filter(filter_line, text)
d = { 'do' : Do, 'enddo': Enddo,
'if' : If, 'endif': Endif,
'_doc': Begin_doc, 'end_doc': End_doc}
assert type(text) == list
def find_matching_end_ifdo(begin,x):
level = 1
for i in range(begin+1,len(text)):
line = text[i]
if type(line) == d[x]:
level += 1
elif type(line) == d["end%s"%(x,)]:
level -= 1
if level == 0:
return True
elif type(line) in [End, End_provider]:
break
error.fail(text[begin],"Missing 'end%s'"%(x,))
def find_matching_end_subfunpro(begin,x):
line = text[begin]
for i in range(begin+1,len(text)):
line = text[i]
if type(line) == x:
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")
level = 0 Note:
for i,line in enumerate(text): fortran 'ifdef' statement may cause this function to bug.
if type(line) == Begin_doc: Indeed we count the numboer of 'x' statement and compare it to the number of 'endx'.
find_matching_end_ifdo(i,'_doc') Maybe more of one 'x' statement in defined cause in 'ifdef/else/endif' statement.
for i,line in enumerate(text): '''
if type(line) == Do:
find_matching_end_ifdo(i,'do')
elif type(line) == If:
find_matching_end_ifdo(i,'if')
elif type(line) in [Subroutine, Function, Program]:
level += 1
find_matching_end_subfunpro(i,End)
elif type(line) == Begin_provider:
level += 1
find_matching_end_subfunpro(i,End_provider)
elif type(line) == End:
level -= 1
elif type(line) == End_provider:
level -= 1
if level < 0:
error.fail(line,"Beginning of block not matched")
return True d_block = {Enddo: [Do],
Endif: [If],
End_provider: [Begin_provider],
End_doc: [Begin_doc],
End: [Program, Subroutine, Function],
End_module: [Module],
End_interface: [Interface]}
from collections import defaultdict
d_type = defaultdict(list)
for line in raw_text:
d_type[type(line)].append(line)
for t_end, l_begin in d_block.iteritems():
n_end = len(d_type[t_end])
n_begin = sum(len(d_type[t_begin]) for t_begin in l_begin)
if n_end != n_begin:
if n_end > n_begin:
logger.error("You have more close statement than open statement (%s) (%s)",line.filename,t_end)
else:
logger.error('You have more end statement than open statenemt for (%s) (%s)' % (line.filename, t_end))
for i in zip([l for i in l_begin for l in d_type[i]], d_type[t_end]):
logger.debug(i)
sys.exit(1)
###################################################################### ######################################################################
def remove_ifdefs(text): def remove_ifdefs(text):
assert type(text) == list assert type(text) == list
result = [] result = []
do_print = True do_print = True
for line in text: for line in text:
if type(line) == Irp_If: if type(line) == Irp_If:
@ -854,66 +875,109 @@ def remove_ifdefs(text):
do_print = not do_print do_print = not do_print
elif type(line) == Irp_Endif: elif type(line) == Irp_Endif:
do_print = True do_print = True
else: elif do_print:
if do_print:
result.append(line) result.append(line)
return result return result
###################################################################### ######################################################################
def check_OpenMP(text): def check_OpenMP(text):
'Not working!'
assert type(text) == list assert type(text) == list
result = []
inside_openmp = False inside_openmp = False
for line in text: for line in text:
if type(line) == Openmp: if type(line) == Openmp:
# Detect OpenMP blocks # Detect OpenMP blocks
buffer = line.text.lower().split() buffer = line.lower.split()
if buffer[1] == "parallel": if buffer[1] == "parallel":
inside_openmp = True inside_openmp = True
if buffer[1] == "end" and buffer[2] == "parallel": elif buffer[1] == "end" and buffer[2] == "parallel":
inside_openmp = False inside_openmp = False
result.append(line)
if inside_openmp: # if inside_openmp and isinstance(line, (Provide_all, Provide, Touch, SoftTouch)):
if type(line) in [ Provide_all, Provide, Touch, SoftTouch ]: # logger.error("%s is not allowed in an OpenMP block: %s" % (type(line),line))
error.fail(line,type(line).str+" is not allowed in an OpenMP block.")
return text
return result
###################################################################### ######################################################################
def create_preprocessed_text(filename): class Preprocess_text(object):
file = open(filename,"r") def __init__(self, filename):
lines = file.readlines() self.filename = filename
file.close()
result = get_text(lines,filename) @irpy.lazy_property_mutable
def text(self):
with open(self.filename, 'r') as f:
str_ = f.read()
#Dirty thing. We will replace 'end program' by 'end subroutine'
#because afterward the program will be replaced by a subroutine...
import re
transform = re.compile(re.escape('end program'), re.IGNORECASE)
return transform.sub('end subroutine', str_)
@irpy.lazy_property_mutable
def text_align(self):
from command_line import command_line
return self.text.replace("$IRP_ALIGN", command_line.align)
@irpy.lazy_property
def text_lower(self):
return self.text_align.lower()
@irpy.lazy_property
def text_lower_canonized(self):
return get_canonized_text(self.text_lower)
@irpy.lazy_property
def lines(self):
return self.text_align.split('\n')
@irpy.lazy_property
def lines_lower(self):
return self.text_lower.split('\n')
@irpy.lazy_property
def lines_lower_canonized(self):
return self.text_lower_canonized.replace("!", " ! ").split('\n')
@irpy.lazy_property
def lines_overloaded(self):
'''Labeled lines'''
result = []
is_doc = False
for i, (l, ll, llc) in enumerate(zip(self.lines, self.lines_lower, self.lines_lower_canonized)):
line, is_doc = get_type(i + 1, self.filename, l, ll, llc, is_doc)
result += line
return result
@irpy.lazy_property
def preprocessed_text(self):
result = self.lines_overloaded
result = execute_templates(result) result = execute_templates(result)
result = execute_shell(result) result = execute_shell(result)
fortran_form = form(result) fortran_form = form(result)
result = remove_ifdefs(result) result = remove_ifdefs(result)
result = remove_comments(result, fortran_form) result = remove_comments(result, fortran_form)
result = remove_continuation(result, fortran_form) result = remove_continuation(result, fortran_form)
result = add_operators(result) result = add_operators(result)
result = change_includes(result) result = change_includes(result)
result = change_single_line_ifs(result) result = change_single_line_ifs(result)
result = process_old_style_do(result) result = process_old_style_do(result)
result = irp_simple_statements(result) result = irp_simple_statements(result)
result = check_OpenMP(result) result = check_OpenMP(result)
check_begin_end(result) check_begin_end(result)
return result return result
######################################################################
preprocessed_text = parallel_loop( lambda x,y: create_preprocessed_text(x), \
map(lambda x: (x,None), irpf90_files ) )
######################################################################
def debug():
for filename, txt in preprocessed_text:
if filename == 'invert.irp.f':
print "=== "+filename+" ==="
for line in txt:
print line
print irpf90_files
if __name__ == '__main__': if __name__ == '__main__':
debug() debug()

View File

@ -52,15 +52,8 @@ def build_rdtsc():
file = open(filename,'w') file = open(filename,'w')
file.write(rdtsc) file.write(rdtsc)
file.close() file.close()
# def t():
# p = subprocess.Popen(["gcc","-O2",filename,"-c","-o","irp_rdtsc.o"])
# p.communicate()
# os.remove(filename)
#
# threading.Thread(target=t).start()
def build_module(): def build_module(variables):
from variables import variables
data = """ data = """
module irp_timer module irp_timer
double precision :: irp_profile(3,%(n)d) double precision :: irp_profile(3,%(n)d)
@ -176,9 +169,7 @@ end
file.write(data) file.write(data)
file.close() file.close()
def run(): def run(d_entity):
build_module() build_module(d_entity)
build_rdtsc() build_rdtsc()
if __name__ == "__main__":
build_rdtsc()

View File

@ -47,7 +47,7 @@ re_decl = re.compile( "".join( [ r"^\ *",
r"|external *(::)?", r"|external *(::)?",
r"|equivalence *(::)?", r"|equivalence *(::)?",
r"|type", r"|type",
r"|end ?type", r"|endtype",
r")[^=(]" r")[^=(]"
] ) ) ] ) )

104
src/routine.py Normal file
View File

@ -0,0 +1,104 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from util import logger
try:
import irpy
except:
import lib_irpy as irpy
class Routine(object):
'''
A collection of list corresponding of a Routine (Subroutine, or function)
'''
############################################################
def __init__(self,text):
assert type(text) == list
assert len(text) > 0
self.text = text
self.prototype = self.text[0]
assert isinstance(self.prototype, (Subroutine, Function))
############################################################
@irpy.lazy_property_mutable
def called_by(self):
raise AttributeError
############################################################
@irpy.lazy_property
def name(self):
'''Name is lowercase'''
return self.prototype.subname
############################################################
@irpy.lazy_property
def is_function(self):
return "function" in self.prototype.lower
############################################################
@irpy.lazy_property
def is_subroutine(self):
return "subroutine" in self.prototype.lower
############################################################
@irpy.lazy_property
def doc(self):
l_doc = [ l for l in self.text if isinstance(l,Doc) ]
if not l_doc:
logger.info("Subroutine '%s' is not documented"%(self.name))
return [l.text.lstrip()[1:] for l in l_doc]
############################################################
@irpy.lazy_property
def touches_my_self(self):
return set(x for line in self.text for x in line.text.split()[1:] if isinstance(line,(Touch, SoftTouch)))
@irpy.lazy_property_mutable
def touches_ancestor(self):
raise AttributeError
@irpy.lazy_property
def touches(self):
return list(self.touches_my_self.union(self.touches_ancestor))
############################################################
@irpy.lazy_property
def regexp(self):
import re
return re.compile(r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
############################################################
@irpy.lazy_property
def calls(self):
return set(line.text.split('(',1)[0].split()[1].lower() for line in self.text if isinstance(line,Call))

View File

@ -1,131 +0,0 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from util import *
import error
class Sub(object):
############################################################
def __init__(self,text):
assert type(text) == list
assert len(text) > 0
assert type(text[0]) in [Subroutine, Function]
self.text = text
self.called_by = []
############################################################
def name(self):
'''Name is lowercase'''
if '_name' not in self.__dict__:
self._name = find_subname(self.line)
return self._name
name = property(name)
############################################################
def is_function(self):
if '_is_function' not in self.__dict__:
self._is_function = "function" in self.line.lower
return self._is_function
is_function = property(is_function)
############################################################
def doc(self):
if '_doc' not in self.__dict__:
def f(l): return
buffer = filter(lambda l:type(l) == Doc, self.text)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Subroutine %s is not documented"%(self.name))
return self._doc
doc = property(doc)
############################################################
def line(self):
if '_line' not in self.__dict__:
self._line = self.text[0]
return self._line
line = property(line)
############################################################
def touches(self):
if '_touches' not in self.__dict__:
from subroutines import subroutines
self._touches = []
for line in filter(lambda x: type(x) in [Touch, SoftTouch],self.text):
self._touches += line.text.split()[1:]
for sub in self.calls:
if sub in subroutines:
self._touches += subroutines[sub].touches
self._touches = make_single(self._touches)
return self._touches
touches = property(touches)
############################################################
def needs(self):
if '_needs' not in self.__dict__:
import parsed_text
self._needs = make_single(self._needs)
return self._needs
needs = property(needs)
############################################################
def to_provide(self):
if '_to_provide' not in self.__dict__:
import parsed_text
return self._to_provide
to_provide = property(to_provide)
############################################################
def regexp(self):
if '_regexp' not in self.__dict__:
import re
self._regexp = re.compile( \
r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
return self._regexp
regexp = property(regexp)
############################################################
def calls(self):
if '_calls' not in self.__dict__:
buffer = filter(lambda x: type(x) == Call,self.text)
self._calls = []
for line in buffer:
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
self._calls = make_single(self._calls)
return self._calls
calls = property(calls)
######################################################################
if __name__ == '__main__':
from preprocessed_text import preprocessed_text
from variables import variables
from subroutines import subroutines
print map(lambda x: variables[x].needs, subroutines['full_ci'].needs)
print subroutines['full_ci'].calls

View File

@ -1,72 +0,0 @@
#!/usr/bin/env python
# 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
from util import *
from subroutine import *
from variables import variables
from variable import Variable
from irpf90_t import *
def create_subroutines():
from preprocessed_text import preprocessed_text
result = {}
for filename, text in preprocessed_text:
buffer = []
inside = False
for line in text:
if type(line) in [ Subroutine, Function ]:
inside = True
if inside:
buffer.append(line)
if isinstance(line,End):
if inside:
v = Sub(buffer)
result[v.name] = v
buffer = []
inside = False
return result
def create_called_by(subs,vars):
for s in subs.values() + vars.values():
if type(s) == Variable and s.same_as != s.name:
continue
for x in s.calls:
try:
subs[x].called_by.append(s.name)
except KeyError:
pass
for s in subs.values():
s.called_by = make_single(s.called_by)
s.called_by.sort()
subroutines = create_subroutines()
create_called_by(subroutines,variables)
if __name__ == '__main__':
for v in subroutines.keys():
print v

View File

@ -24,50 +24,42 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
from irpf90_t import irp_id,irpdir
import os
from util import lazy_write_file
from irpf90_t import * def create(modules,variables):
from util import * # (Dict[str,Module]. Dict[str, Variable]) -> None
from variables import variables '''Create the fortran90 finalize subroutine and the touched one'''
from modules import modules
FILENAME=irpdir+'irp_touches.irp.F90'
def create():
out = []
l = variables.keys()
l.sort
main_modules = filter(lambda x: modules[x].is_main, modules)
finalize = "subroutine irp_finalize_%s\n"%(irp_id) finalize = "subroutine irp_finalize_%s\n"%(irp_id)
for m in filter(lambda x: not modules[x].is_main, modules): for m in filter(lambda x: not modules[x].is_main and modules[x].has_irp_module, modules):
finalize += " use %s\n"%(modules[m].name) finalize += " use %s\n"%(modules[m].name)
for v in l:
var = variables[v] main_modules_name =[ m.name for m in modules.values() if m.is_main]
var_in_main = False
for m in main_modules: out = []
if var.fmodule == modules[m].name: for v,var in variables.iteritems():
var_in_main = True
break if var.fmodule not in main_modules_name:
if not var_in_main: #if var.is_self_touched:
if var.is_touched:
out += var.toucher out += var.toucher
if var.dim != []: if var.dim:
finalize += " if (allocated(%s)) then\n"%v finalize += " if (allocated(%s)) then\n"%v
finalize += " %s_is_built = .False.\n"%var.same_as finalize += " %s_is_built = .False.\n"%var.same_as
finalize += " deallocate(%s)\n"%v finalize += " deallocate(%s)\n"%v
finalize += " endif\n" finalize += " endif\n"
finalize += "end\n" finalize += "end\n"
if out:
if out != []:
out = map(lambda x: "%s\n"%(x),out) out = map(lambda x: "%s\n"%(x),out)
out += finalize out += finalize
if not same_file(FILENAME,out): filename=os.path.join(irpdir,'irp_touches.irp.F90')
file = open(FILENAME,'w') lazy_write_file(filename,''.join(out))
file.writelines(out)
file.close()
if __name__ == '__main__': if __name__ == '__main__':
create() create()

View File

@ -24,169 +24,282 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import os
NTHREADS=1 #int(os.getenv('OMP_NUM_THREADS',1))
def strip(x): # ~#~#~#~#~#
return x.strip() # L o g e r
# ~#~#~#~#~#
'''
Level Numeric value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
'''
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('Irpf90')
logger.setLevel(30)
def lower(x): # ~#~#~#~#~#
return x.lower() # / / _ R E L A T E D
# ~#~#~#~#~#
def same_file(filename,txt): def chunkify(l,n_chunk):
assert isinstance(filename,str) # (List[any], int) -> List [ List[any] ]
if (type(txt) == list): '''Split the list on n_chunk'''
buffer = ''.join(txt) len_ = len(l)
else: n = max(1, len_ / n_chunk )
buffer = txt return [ l[i:i + n] for i in xrange(0, len_, n) ]
import multiprocessing
def parmap(f, it, parallel=False):
# (Callable, Iterable, bool) -> List
'''Parallel version of the std map function
The parallel flag is set to togle the // execusion
Note:
- We try to use the Mulprocesses map is possible else we use our own
- The order of the sequence if concerved
- Will use all the processesor possible
- We return a List
- The traceback is loose if an error occur but a Exception is raise.
'''
if not parallel:
return map(f, it)
nproc = multiprocessing.cpu_count()
# ~!~!~!
# Parallelisation STD
# ~!~!~
# This 'hang' on Travis and I don't know why...
# https://docs.python.org/2/library/pickle.html#what-can-be-pickled-and-unpickled
#from cPickle import PicklingError
#try:
# p = multiprocessing.Pool(nproc)
# l_res = p.map(f, it,nproc)
#except PicklingError:
# pass
#else:
# return l_res
# ~!~!~!
# Parallelisation By Us
# ~!~!~
# To optimize the // performance,
# we merge the task into chunk
# In this implementation, we minimizise the communication
# (aka 1 job by processor)
it_chunk = chunkify(l=it,n_chunk=nproc)
def F(chunk):
# (List[any]) -> (List[any])
'''Same as 'f' but for a chunck'''
return map(f,chunk)
q_in = multiprocessing.JoinableQueue()
q_out = multiprocessing.Queue()
# All the worker will sepuku after reseaving this message
# Remove that we need to always put in `q_in` a not None value.
stop_condition = None
def worker():
# () -> None
'''Read a task from q_in, excute it, and store it in q_out
Note:
- We use 'F' and not 'f'.
- The for loop will break when stop_contition occur
- We get, and put an idx to allow the possibility of ordering afterward
- We store any exeception, to raise her afterward
'''
for i, x in iter(q_in.get, stop_condition):
try: try:
file = open(filename,"r") result = F(x)
except BaseException as e:
t = e
else:
t = (i, result)
q_out.put(t)
q_in.task_done()
q_in.task_done()
# Process' creation
l_proc = [multiprocessing.Process(target=worker) for _ in range(nproc)]
for p in l_proc:
p.daemon = True
p.start()
# Add the job to the queue (Note we add an idx, this will all)
for i, x in enumerate(it_chunk):
q_in.put((i, x))
# Now add the stop contidion and join
# (Because q_in.get is blocking we don't need to join the queue before)
for _ in l_proc:
q_in.put(stop_condition)
q_in.join()
# Get all the chunk and join the process
l_res = [q_out.get() for _ in range(len(it_chunk))]
for p in l_proc:
p.join()
# Check if error have occured
try:
from itertools import ifilter
e = next(ifilter(lambda t: isinstance(t,BaseException), l_res))
except StopIteration:
# Now we need first to order the result, and secondly to flatte it
return [item for _, chunk in sorted(l_res) for item in chunk]
else:
raise e
# ~#~#~#~#~#
# I O _ R E L A T E D
# ~#~#~#~#~#
import hashlib
import os
def cached_file(filename, text):
# (str,str) -> bool
'''Check if file locatte at filename containt the same data as text
Return:
True if data is the same, false otherwise
'''
def digest(data):
# (str) -> str
'''compute an uniq data id'''
return hashlib.md5(data).hexdigest()
try:
text_ref = open(filename, 'rb').read()
except IOError: except IOError:
return False return False
stream = file.read() else:
file.close() return digest(text_ref) == digest(text)
if len(stream) != len(buffer):
return False
if stream != buffer:
return False
return True
def build_dim(dim): def lazy_write_file(filename, text, conservative=False,touch=False):
if len(dim) == 0: # (str, str, bool) -> None
'''Write data lazily in filename location.
Note:
If convervative is set, we don't overwrite.
'''
if not os.path.exists(filename) or not cached_file(filename, text) and not conservative:
with open(filename, 'w') as f:
f.write(text)
elif touch:
os.utime(filename,None)
def listdir(directory, abspath=False):
#(str, bool) -> List[str]
'''Replacement of the std:listdir but with the possibility to get the abosulte path'''
l_filename = os.listdir(directory)
if not abspath:
return l_filename
else:
return [os.path.abspath(os.path.join(directory, f)) for f in l_filename]
def check_output(*popenargs, **kwargs):
"""Run command with arguments and return its output as a byte string.
Backported from Python 2.7 as it's implemented as pure python on stdlib.
>>> check_output(['/usr/bin/python', '--version'])
Python 2.6.2
"""
import subprocess
process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
error = subprocess.CalledProcessError(retcode, cmd)
error.output = output
raise error
return output
# ~#~#~#~#~#
# L i s t
# ~#~#~#~#~#
def uniquify(l,sort=False):
# (Iter, bool) -> List[Any]
'''Uniquify a immutable iterable. Don't preserve the order'''
r = list(set(l))
if not sort:
return r
else:
return sorted(r)
def OrderedUniqueList(l):
# (Iter, bool) -> List[Any]
'''Uniquify a immutable iterable. Don't preserve the order'''
return sorted(set(l))
def flatten(l_2d):
# (List [ List[Any] ]) -> List
'''Construct a copy of the 2d list collapsed into one dimension.
Note:
- We collapse in a C-style fashion (row_major).
'''
return [item for l_1d in l_2d for item in l_1d]
# ~#~#~#~#~#
# I R P _ R E L A T E D
# ~#~#~#~#~#
def build_dim(l_dim, colons=False):
# (List[str],bool) -> str
'''Contruct a valid fortran90 array dimension code from a list dimension
Exemple:
[4,8] -> (4,8) if not colons
[4,8] -> (:,:) if colons
'''
if not l_dim:
return "" return ""
else:
return "(%s)"%( ",".join(dim) )
def build_dim_colons(v): l_dim_colons = [':'] * len(l_dim) if colons else l_dim
d = v.dim
if d == []: return "(%s)" % (",".join(l_dim_colons))
return ""
else:
x = map(lambda x: ":", d)
return "(%s)"%(','.join(x))
import error def build_use(l_ent, d_ent):
def find_subname(line): # (List, Dict[str,Entity]) -> list
buffer = line.lower '''Contruct the fortran90 'use' statement for the list of entity'''
if not buffer.endswith(')'): return OrderedUniqueList(" use %s" % d_ent[x].fmodule for x in l_ent)
buffer += "()"
buffer = buffer.split('(')
buffer = buffer[0].split()
if len(buffer) < 2:
error.fail(line,"Syntax Error")
return buffer[-1]
def make_single(l): def build_call_provide(l_ent, d_ent):
d = {} # (List, Dict[str,Entity]) -> list
for x in l: '''Construct the fortran 90 call the provider needed by the list of entity'''
d[x] = True def fun(x):
return d.keys() return [ " if (.not.%s_is_built) then" % x,
" call provide_%s" % x,
" endif"]
def flatten(l): # Get the corect name (in the case of multiple provider line)
if type(l) == list: l_same_as = OrderedUniqueList(d_ent[x].same_as for x in l_ent)
result = [] return flatten(map(fun, l_same_as))
for i in range(len(l)):
elem = l[i]
result += flatten(elem)
return result
else:
return [l]
def dimsize(x):
assert isinstance(x,str)
buffer = x.split(':')
if len(buffer) == 1:
return x
else:
assert len(buffer) == 2
size = ""
b0, b1 = buffer
if b0.replace('-','').isdigit() and b1.replace('-','').isdigit():
size = str( int(b1) - int(b0) + 1 )
else:
if b0.replace('-','').isdigit():
size = "(%s) - (%d)"%(b1,int(b0)-1)
elif b1.replace('-','').isdigit():
size = "(%d) - (%s)"%(int(b1)+1,b0)
else:
size = "(%s) - (%s) + 1"%(b1,b0)
return size
def put_info(text,filename):
assert type(text) == list
if len(text) > 0:
assert type(text[0]) == tuple
from irpf90_t import Line
assert type(text[0][0]) == list
assert isinstance(text[0][1], Line)
lenmax = 80 - len(filename)
format = "%"+str(lenmax)+"s ! %s:%4s"
for vars,line in text:
line.text = format%(line.text.ljust(lenmax),line.filename,str(line.i))
return text
import cPickle as pickle
import os, sys
def parallel_loop(f,source):
pidlist = range(NTHREADS)
src = [ [] for i in xrange(NTHREADS) ]
index = 0
try:
source = map( lambda x: (len(x[1]),(x[0], x[1])), source )
source.sort()
source = map( lambda x: x[1], source )
except:
pass
for i in source:
index += 1
if index == NTHREADS:
index = 0
src[index].append(i)
thread_id = 0
fork = 1
r = range(0,NTHREADS)
for thread_id in xrange(1,NTHREADS):
r[thread_id], w = os.pipe()
fork = os.fork()
if fork == 0:
os.close(r[thread_id])
w = os.fdopen(w,'w')
break
else:
os.close(w)
r[thread_id] = os.fdopen(r[thread_id],'r')
pidlist[thread_id] = fork
thread_id = 0
result = []
for filename, text in src[thread_id]:
result.append( (filename, f(filename,text)) )
result.sort()
if fork == 0:
pickle.dump(result,w,-1)
w.close()
os._exit(0)
for i in xrange(1,NTHREADS):
result += pickle.load(r[i])
r[i].close()
os.waitpid(pidlist[i],0)[1]
return result
if __name__ == '__main__':
print "10",dimsize("10") #-> "10"
print "0:10",dimsize("0:10") # -> "11"
print "0:x",dimsize("0:x") # -> "x+1"
print "-3:x",dimsize("-3:x") # -> "x+1"
print "x:y",dimsize("x:y") # -> "y-x+1"
print "x:5",dimsize("x:5") # -> "y-x+1"

View File

@ -1,697 +0,0 @@
#!/usr/bin/env python
# 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
from irpf90_t import *
from util import *
import error
from command_line import command_line
class Variable(object):
############################################################
def __init__(self,text,label,name = None):
assert type(text) == list
assert len(text) > 0
assert type(text[0]) == Begin_provider
self.label = label
self.text = text
if name is not None:
self._name = name
############################################################
def is_touched(self):
if '_is_touched' not in self.__dict__:
from variables import variables
result = self.is_read
for i in self.children:
if variables[i].is_touched:
result = True
break
self._is_touched = result
return self._is_touched
is_touched = property(is_touched)
############################################################
def has_openmp(self):
if '_has_openmp' not in self.__dict__:
self._has_openmp = False
self.builder()
return self._has_openmp
has_openmp = property(has_openmp)
############################################################
def is_written(self):
if '_is_written' not in self.__dict__:
from variables import variables
result = False
for i in self.parents:
if variables[i].is_written:
result = True
break
self._is_written = result
return self._is_written
is_written = property(is_written)
############################################################
def is_read(self):
if '_is_read' not in self.__dict__:
from variables import variables
result = False
for i in self.parents:
if variables[i].is_read:
result = True
break
self._is_read = result
return self._is_read
is_read = property(is_read)
############################################################
def is_main(self):
if '_is_main' not in self.__dict__:
self._is_main = (self.name == self.same_as)
return self._is_main
is_main = property(is_main)
############################################################
def name(self):
'''Name is lowercase'''
if '_name' not in self.__dict__:
buffer = None
text = self.text
for line in text:
if type(line) == Begin_provider:
self._name = line.filename[1]
break
return self._name
name = property(name)
############################################################
def doc(self):
if '_doc' not in self.__dict__:
text = self.text
buffer = filter(lambda l:type(l) == Doc, text)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Variable %s is not documented"%(self.name))
return self._doc
doc = property(doc)
############################################################
def documented(self):
if '_documented' not in self.__dict__:
self._documented = (self.doc != [])
return self._documented
documented = property(documented)
############################################################
def includes(self):
if '_includes' not in self.__dict__:
self._includes = []
text = self.text
for line in filter(lambda x: type(x) == Include,text):
self._includes.append(line.filename)
make_single(self._includes)
return self._includes
includes = property(includes)
############################################################
def calls(self):
if '_calls' not in self.__dict__:
self._calls = []
text = self.text
for line in filter(lambda x: type(x) == Call,text):
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
make_single(self._calls)
return self._calls
calls=property(fget=calls)
############################################################
def others(self):
if '_others' not in self.__dict__:
result = []
append = result.append
f = lambda l: type(l) in [Begin_provider, Cont_provider]
text = self.text
lines = filter(f, text)
for line in lines:
append(line.filename[1])
result.remove(self.name)
self._others = result
return self._others
others = property(others)
############################################################
def same_as(self):
if '_same_as' not in self.__dict__:
if type(self.line) == Begin_provider:
result = self.name
else:
result = self.text[0].filename[1]
self._same_as = result
return self._same_as
same_as = property(same_as)
############################################################
def allocate(self):
if '_allocate' not in self.__dict__:
if not self.is_main:
self._allocate = []
else:
from variables import variables
def f(var):
return variables[var].dim != []
self._allocate = filter ( f, self.others + [self.name] )
return self._allocate
allocate = property(allocate)
############################################################
def dim(self):
if '_dim' not in self.__dict__:
line = self.line.text.split('!')[0]
buffer = line.replace(']','').split(',',2)
if len(buffer) == 2:
self._dim = []
else:
buffer = buffer[2].strip()[1:-1].split(',')
self._dim = map(strip,buffer)
return self._dim
dim = property(dim)
############################################################
def type(self):
if '_type' not in self.__dict__:
line = self.line.text
buffer = line.split(',')[0]
try:
buffer = buffer.split('[')[1].strip()
except IndexError:
error.fail(None,"Error in definition of %s."%(self.name))
if self.dim != []:
buffer = "%s, allocatable"%(buffer)
self._type = buffer
return self._type
type = property(type)
############################################################
def fmodule(self):
if '_fmodule' not in self.__dict__:
self._fmodule = self.line.filename[0].replace('/','__').split('.irp.f')[0]+'_mod'
return self._fmodule
fmodule = property(fmodule)
############################################################
def regexp(self):
if '_regexp' not in self.__dict__:
import re
self._regexp = re.compile( \
r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
return self._regexp
regexp = property(regexp)
############################################################
def line(self):
if '_line' not in self.__dict__:
f = lambda l: type(l) in [Begin_provider, Cont_provider]
text = self.text
lines = filter(f, text)
for line in lines:
buffer = line.filename[1]
if self._name == buffer:
self._line = line
break
assert '_line' in self.__dict__
return self._line
line = property(line)
############################################################
def header(self):
if '_header' not in self.__dict__:
name = self.name
self._header = [ " %s :: %s %s"%(self.type, name, build_dim_colons(self) ) ]
if command_line.coarray:
if self.dim == []:
self._header[0] += " [*]"
else:
self._header[0] += " [:]"
if self.dim != [] and command_line.align != '1':
self._header += [" !DIR$ ATTRIBUTES ALIGN: %s :: %s"%(command_line.align,name)]
if self.is_main:
self._header += [ " logical :: %s_is_built = .False."%(name) ]
return self._header
header = property(header)
############################################################
def toucher(self):
if '_toucher' not in self.__dict__:
if not self.is_main:
self._toucher = []
else:
from modules import modules
from variables import variables
if '_needed_by' not in self.__dict__:
import parsed_text
parents = self.parents
parents.sort()
mods = map(lambda x: variables[x].fmodule, parents)
mods = make_single(mods)+[self.fmodule]
name = self.name
result = [ "subroutine touch_%s"%(name) ]
result += map(lambda x: " Use %s"%(x),mods)
result.append(" implicit none")
if command_line.do_debug:
length = str(len("touch_%s"%(name)))
result += [ " character*(%s) :: irp_here = 'touch_%s'"%(length,name) ]
if command_line.do_debug:
result += [ " call irp_enter(irp_here)" ]
result += map( lambda x: " %s_is_built = .False."%(x), parents)
result.append(" %s_is_built = .True."%(name))
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine touch_%s"%(name))
result.append("")
self._toucher = result
return self._toucher
toucher = property(toucher)
##########################################################
def locker(self):
if '_locker' not in self.__dict__:
if not command_line.do_openmp:
self._locker = []
else:
from modules import modules
from variables import variables
name = self.name
result = [ "subroutine irp_lock_%s(set)"%(name) ]
result += [ " use omp_lib",
" implicit none",
" logical, intent(in) :: set",
" integer(kind=omp_nest_lock_kind),save :: %s_lock"%(name),
" integer,save :: ifirst",
]
if command_line.do_debug:
length = str(len("irp_lock_%s"%(name)))
result += [ " character*(%s) :: irp_here = 'irp_lock_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += [ " if (ifirst == 0) then",
" ifirst = 1",
" call omp_init_nest_lock(%s_lock)"%(name),
" endif",
" if (set) then",
" call omp_set_nest_lock(%s_lock)"%(name),
" else",
" call omp_unset_nest_lock(%s_lock)"%(name),
" endif",
]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine irp_lock_%s"%(name))
result.append("")
self._locker = result
return self._locker
locker = property(locker)
##########################################################
def reader(self):
if '_reader' not in self.__dict__:
if not self.is_main:
self._reader = []
else:
if '_needs' not in self.__dict__:
import parsed_text
from variables import variables
name = self.name
result = [ \
"subroutine reader_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("reader_%s"%(self.name))
result += [\
" character*(%d) :: irp_here = 'reader_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += map(lambda x: " call reader_%s(irp_num)"%(x),self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo"]
for n in [ name ]+self.others:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='OLD',action='READ')"%(n),
" read(irp_iunit,*) %s%s"%(n,build_dim_colons(variables[n])),
" close(irp_iunit)" ]
result += [ \
" call touch_%s"%(name),
" %s_is_built = .True."%(name) ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine reader_%s"%(name))
result.append("")
self._reader = result
return self._reader
reader = property(reader)
##########################################################
def writer(self):
if '_writer' not in self.__dict__:
if not self.is_main:
self._writer = []
else:
from variables import variables
if '_needs' not in self.__dict__:
import parsed_text
name = self.name
result = [ \
"subroutine writer_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("writer_%s"%(self.name))
result += [\
" character*(%d) :: irp_here = 'writer_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += [ \
" if (.not.%s_is_built) then"%(self.same_as),
" call provide_%s"%(self.same_as),
" endif" ]
result += map(lambda x: " call writer_%s(irp_num)"%(x),self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo" ]
for n in [ name ] + self.others:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='UNKNOWN',action='WRITE')"%(n),
" write(irp_iunit,*) %s%s"%(n,build_dim_colons(variables[n])),
" close(irp_iunit)" ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine writer_%s"%(name))
result.append("")
self._writer = result
return self._writer
writer = property(writer)
##########################################################
def free(self):
if '_free' not in self.__dict__:
name = self.name
result = [ "!","! >>> FREE %s"%(name),
" %s_is_built = .False."%(self.same_as) ]
if self.dim != []:
if command_line.do_memory:
result += [ \
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name),
" print *, 'Deallocating %s'"%(name),
" endif" ]
else:
result += [ \
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name),
" endif" ]
result.append("! <<< END FREE")
self._free = result
return self._free
free = property(free)
##########################################################
def provider(self):
if '_provider' not in self.__dict__:
if not self.is_main:
self._provider = []
else:
if '_to_provide' not in self.__dict__:
import parsed_text
from variables import variables, build_use, call_provides
name = self.name
same_as = self.same_as
def build_alloc(name):
self = variables[name]
if self.dim == []:
return []
def do_size():
result = " print *, ' size: ("
result += ','.join(self.dim)
return result+")'"
def check_dimensions():
result = map(lambda x: "(%s>0)"%(dimsize(x)), self.dim)
result = ".and.".join(result)
result = " if (%s) then"%(result)
return result
def dimensions_OK():
result = [ " irp_dimensions_OK = .True." ]
for i,k in enumerate(self.dim):
result.append(" irp_dimensions_OK = irp_dimensions_OK.AND.(SIZE(%s,%d)==(%s))"%(name,i+1,dimsize(k)))
return result
def do_allocate():
if command_line.coarray:
result = " allocate(%s(%s)[*],stat=irp_err)"
else:
result = " allocate(%s(%s),stat=irp_err)"
result = result%(name,','.join(self.dim))
if command_line.do_memory:
tmp = "\n print *, %s, 'Allocating %s(%s)'"
d = ','.join(self.dim)
result += tmp%('size('+name+')',name,d)
return result
result = [ " if (allocated (%s) ) then"%(name) ]
result += dimensions_OK()
result += [\
" if (.not.irp_dimensions_OK) then",
" deallocate(%s,stat=irp_err)"%(name),
" if (irp_err /= 0) then",
" print *, irp_here//': Deallocation failed: %s'"%(name),
do_size(),
" endif"]
if command_line.do_memory:
result += [\
" print *, 'Deallocating %s'"%(name) ]
result.append(check_dimensions())
result.append(do_allocate())
result += [\
" if (irp_err /= 0) then",
" print *, irp_here//': Allocation failed: %s'"%(name),
do_size(),
" endif",
" endif",
" endif",
" else" ]
result.append(check_dimensions())
result.append(do_allocate())
result += [\
" if (irp_err /= 0) then",
" print *, irp_here//': Allocation failed: %s'"%(name),
do_size(),
" endif",
" endif",
" endif" ]
return result
result = []
if command_line.directives and command_line.inline in ["all","providers"]:
result += [ "!DEC$ ATTRIBUTES FORCEINLINE :: provide_%s"%(name) ]
result += [ "subroutine provide_%s"%(name) ]
result += build_use( [same_as]+self.to_provide )
if command_line.do_openmp:
result += [" use omp_lib"]
result.append(" implicit none")
length = len("provide_%s"%(name))
result += [\
" character*(%d) :: irp_here = 'provide_%s'"%(length,name),
" integer :: irp_err ",
" logical :: irp_dimensions_OK",
"!$ integer :: nthreads"]
if command_line.do_openmp:
result.append(" call irp_lock_%s(.True.)"%(same_as))
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_enter(irp_here)")
result += call_provides(self.to_provide)
result += flatten( map(build_alloc,[self.same_as]+self.others) )
result += [ " if (.not.%s_is_built) then"%(same_as),
" call bld_%s"%(same_as),
" %s_is_built = .True."%(same_as), "" ]
result += [ " endif" ]
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_leave(irp_here)")
if command_line.do_openmp:
result.append(" call irp_lock_%s(.False.)"%(same_as))
result.append("end subroutine provide_%s"%(name) )
result.append("")
self._provider = result
return self._provider
provider = property(provider)
##########################################################
def builder(self):
if '_builder' not in self.__dict__:
if not self.is_main:
self._builder = []
else:
import parsed_text
from variables import build_use, call_provides
for filename,buffer in parsed_text.parsed_text:
if self.line.filename[0].startswith(filename):
break
text = []
same_as = self.same_as
inside = False
for vars,line in buffer:
if type(line) == Begin_provider:
if line.filename[1] == same_as:
inside = True
vars = []
if inside:
text.append( (vars,line) )
text += map( lambda x: ([],Simple_line(line.i,x,line.filename)), call_provides(vars) )
if command_line.do_profile and type(line) == Begin_provider:
text.append( ( [], Declaration(line.i," double precision :: irp_rdtsc, irp_rdtsc1, irp_rdtsc2",line.filename) ) )
text.append( ( [], Simple_line(line.i," irp_rdtsc1 = irp_rdtsc()",line.filename) ) )
if type(line) == End_provider:
if inside:
break
name = self.name
text = parsed_text.move_to_top(text,Declaration)
text = parsed_text.move_to_top(text,Implicit)
text = parsed_text.move_to_top(text,Use)
text = map(lambda x: x[1], text)
# inside_omp = False
for line in filter(lambda x: type(x) not in [ Begin_doc, End_doc, Doc], text):
if type(line) == Begin_provider:
result = []
if command_line.directives and command_line.inline in ["all","builders"]:
result += [ "!DEC$ ATTRIBUTES INLINE :: bld_%s"%(same_as) ]
result += [ "subroutine bld_%s"%(name) ]
result += build_use([name]+self.needs)
elif type(line) == Cont_provider:
pass
elif type(line) == End_provider:
if command_line.do_profile:
result += [ " irp_rdtsc2 = irp_rdtsc()" ,
" call irp_set_timer(%d,(irp_rdtsc2-irp_rdtsc1))"%self.label ]
result.append( "end subroutine bld_%s"%(name) )
break
elif type(line) == Openmp:
# Detect OpenMP blocks
buffer = line.text.lower().split()
if buffer[1] == "parallel":
# inside_omp = True
self._has_openmp = True
# if buffer[1] == "end" and buffer[2] == "parallel":
# inside_omp = False
result.append(line.text)
else:
# if inside_omp:
# if type(line) in [ Provide_all, Provide, Touch, SoftTouch ]:
# error.fail(line,str(type(line))+"is not allowed in an OpenMP block.")
result.append(line.text)
self._builder = result
return self._builder
builder = property(builder)
##########################################################
def children(self):
if '_children' not in self.__dict__:
if not self.is_main:
self._children = []
from variables import variables
if '_needs' not in self.__dict__:
import parsed_text
result = []
for x in self.needs:
result.append(x)
try:
result += variables[x].children
except RuntimeError:
pass # Exception will be checked after
self._children = make_single(result)
if self.name in result:
error.fail(self.line,"Cyclic dependencies:\n%s"%(str(self._children)))
return self._children
children = property(children)
##########################################################
def parents(self):
if '_parents' not in self.__dict__:
if not self.is_main:
self._parents = []
else:
from variables import variables
if '_needed_by' not in self.__dict__:
import parsed_text
result = []
for x in self.needed_by:
result.append(x)
try:
result += variables[x].parents
except RuntimeError:
pass # Exception will be checked after
self._parents = make_single(result)
if self.name in result:
error.fail(self.line,"Cyclic dependencies:\n%s"%(str(self._parents)))
return self._parents
parents = property(parents)
######################################################################
if __name__ == '__main__':
from preprocessed_text import preprocessed_text
from variables import variables
#for v in variables.keys():
# print v
def print_dot(x,done):
if x.children == []:
return
for i in x.needs:
pair = (x.name, i)
if pair not in done:
print "%s -> %s"%( x.name, i )
done[pair] = None
print_dot(variables[i],done)
print "digraph G { "
# print_dot(variables['e_loc'], {})
print_dot(variables['psi_value'], {})
print "}"

View File

@ -1,96 +0,0 @@
#!/usr/bin/env python
# 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
from variable import *
from irpf90_t import *
from command_line import command_line
from util import *
######################################################################
def create_variables():
from preprocessed_text import preprocessed_text
result = {}
icount = 0
for filename, text in preprocessed_text:
buffer = []
inside = False
for line in text:
if type(line) == Begin_provider:
inside = True
if inside:
buffer.append(line)
if type(line) == End_provider:
inside = False
icount += 1
v = Variable(buffer,icount)
if v.name in result:
print "Warning: Duplicate provider for %s in"%(v.name)
print "- ", v.line.filename[0], " line ", v.line.i
print "- ", result[v.name].line.filename[0], " line ", result[v.name].line.i
print "Choosing first version"
result[v.name] = v
for other in v.others:
if other in result:
print "Warning: Duplicate provider for %s in"%(other)
print "- ", v.line.filename[0], " line ", v.line.i
print "- ", result[other].line.filename[0], " line ", result[other].line.i
print "Choosing first version"
result[other] = Variable(buffer,icount,other)
buffer = []
return result
variables = create_variables()
######################################################################
def build_use(vars):
result = map(lambda x: " use %s"%(variables[x].fmodule), vars)
result = make_single(result)
return result
######################################################################
def call_provides(vars,opt=False):
vars = make_single( map(lambda x: variables[x].same_as, vars) )
if opt:
all_children = flatten( map(lambda x: variables[x].children, vars ))
vars = filter(lambda x: x not in all_children,vars)
def fun(x):
result = []
result += [ \
" if (.not.%s_is_built) then"%(x) ]
result += [ \
" call provide_%s"%(x) ]
result += [ \
" endif" ]
return result
result = flatten ( map (fun, vars) )
return result
######################################################################
if __name__ == '__main__':
for v in variables.keys():
print v

View File

@ -1 +1 @@
version = "1.6.9" version = "2.0.0"