10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-06-02 11:25:19 +02:00

Merge /home/scemama/Thomas/irpf90

This commit is contained in:
Anthony Scemama 2017-07-11 23:31:31 +02:00
commit f1ec5683c6
39 changed files with 4620 additions and 1647 deletions

View File

@ -1,21 +1,27 @@
IRPF90= irpf90 # make | ninja
IRPF90FLAGS= -I ./ -I input/ ##############
BUILD_SYSTEM= make
BUILD_SYSTEM= ninja
#######
IRPF90= ../bin/irpf90
IRPF90FLAGS= -I input --codelet=v:100
.EXPORT_ALL_VARIABLES: .EXPORT_ALL_VARIABLES:
AR = ar
CC = gcc
CFLAGS = -O2
CXX = g++
CXXFLAGS = -O2
FC = gfortran
FCFLAGS = -O2
LIB = LIB =
RANLIB = ranlib
OBJ =
SRC = SRC =
OBJ =
# Compiler ! Will be overwriten by the ENV one if avalaible.
FC =ifort
FCFLAGS ?= -O2
CC ?= gcc
CFLAGS ?= -O2
CXX ?= g++
CXXFLAGS ?= -O2
# Dark magic below modify with caution! # Dark magic below modify with caution!
# "You are Not Expected to Understand This" # "You are Not Expected to Understand This"
@ -32,38 +38,57 @@ SRC =
# | | I _________ # | | I _________
# | | I c(` ')o # | | I c(` ')o
# | l I \. ,/ # | l I \. ,/
# _/j L l\_! _//^---^\\_ # _/j L l\_! _// \\_
#Misc
AR ?=
RANLIB ?=
ifeq ($(BUILD_SYSTEM),ninja) # Variable need by IRPF90
BUILD_FILE=IRPF90_temp/build.ninja BUILD_SYSTEM_stripped=$(strip $(BUILD_SYSTEM))
IRPF90FLAGS += -j ifeq ($(BUILD_SYSTEM_stripped),ninja)
else ifeq ($(BUILD_SYSTEM),make) BUILD_FILE=IRPF90_temp/build.ninja
BUILD_FILE=IRPF90_temp/build.make IRPF90FLAGS += -j
BUILD_SYSTEM += -j else ifeq ($(BUILD_SYSTEM_stripped),make)
BUILD_FILE=IRPF90_temp/build.make
BUILD_SYSTEM += -j
else else
DUMMY: DUMMY:
$(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)') $(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)')
endif endif
define run_and_touch # Actual Rule
$(BUILD_SYSTEM) -C $(dir $(1) ) -f $(notdir $(1) ) $(addprefix $(CURDIR)/, $(2)) && touch $(2) EXE := $(shell egrep -ri '^\s*program' *.irp.f | cut -d'.' -f1)
ARCH = $(addprefix $(CURDIR)/,IRPF90_temp/irpf90.a)
.PHONY: clean all
all: $(EXE)
define run
$(BUILD_SYSTEM_stripped) -C $(dir $(BUILD_FILE) ) -f $(notdir $(BUILD_FILE) ) $(1)
endef endef
EXE := $(shell egrep -r '^\s*program' *.irp.f | awk '{print $$2}') #We allow for the user to ask for 'relative' path
#But the IRPF90 build system use absolute path.
$(EXE): $(ARCH)
@printf "%b" "\033[0;32m Build $@...\033[m\n"
@$(call run, $(addprefix $(CURDIR)/, $@)) && touch $@
.PHONY: all
all: $(BUILD_FILE) .NOTPARALLEL: $(BUILD_FILE) $(ARCH)
$(call run_and_touch, $<, $(EXE))
$(ARCH): $(BUILD_FILE)
@printf "%b" "\033[0;32m Creating the archive...\033[m\n"
@$(call run, $@) && touch $@
.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) $(BUILD_FILE): $(shell find . -maxdepth 2 -path ./IRPF90_temp -prune -o -name '*.irp.f' -print)
$(IRPF90) $(IRPF90FLAGS) @printf "%b" "\033[0;32m Running the IRPF90-compiler...\033[m\n"
@$(IRPF90) $(IRPF90FLAGS)
clean: clean:
rm -f -- $(BUILD_FILE) $(EXE) $(shell find IRPF90_temp -type f \( -name "*.o" -o -name "*.mod" -name "*.a" \) -delete;) rm -f -- $(BUILD_FILE) $(EXE)
veryclean: clean veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags rm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags

View File

@ -1,6 +1,6 @@
program irp_example2 program irp_example2
print *, "Example 2" print *, "Example 2"
print *, 't = ', t print *, 'v = ', v
IRP_WRITE t IRP_WRITE t

View File

@ -1,28 +1,31 @@
BEGIN_PROVIDER [integer, t ] BEGIN_PROVIDER [integer, t ]
IMPLICIT NONE
t = u1+v+4 t = u1+v+4
END_PROVIDER END_PROVIDER
BEGIN_PROVIDER [integer,w] BEGIN_PROVIDER [integer,w]
IMPLICIT NONE
w = d5+3 w = d5+3
END_PROVIDER END_PROVIDER
BEGIN_PROVIDER [ integer, v ] BEGIN_PROVIDER [ integer, v ]
implicit none IMPLICIT NONE
v = u2+w+2 v = u2+w+2
END_PROVIDER END_PROVIDER
BEGIN_PROVIDER [ integer, u1 ] BEGIN_PROVIDER [ integer, u1 ]
IMPLICIT NONE
integer :: fu integer :: fu
u1 = fu(d1,d2) u1 = fu(d1,d2)
END_PROVIDER END_PROVIDER
BEGIN_PROVIDER [ integer, u2 ] BEGIN_PROVIDER [ integer, u2 ]
IMPLICIT NONE
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)
integer :: x,y INTEGER, INTENT(in) :: x,y
fu = x+y+1 fu = x+y+1
end function END FUNCTION

View File

@ -36,6 +36,7 @@ irp_id = irpf90_t.irp_id
cwd = os.getcwd() cwd = os.getcwd()
def dress(f, in_root=False): def dress(f, in_root=False):
#(str,bool) -> str #(str,bool) -> str
""" Transfoms the filename into $PWD/IRPF90_temp/f """ Transfoms the filename into $PWD/IRPF90_temp/f
@ -65,9 +66,7 @@ def create_build_touches(l_irp_m, ninja):
result_ninja = '\n'.join([ result_ninja = '\n'.join([
"build {target_o}: compile_fortran_{irp_id} {target_F90} | {list_of_modules_irp}", "build {target_o}: compile_fortran_{irp_id} {target_F90} | {list_of_modules_irp}",
" short_in = {short_target_F90}", " short_in = {short_target_F90}", " short_out = {short_target_o}", ""
" short_out = {short_target_o}",
""
]) ])
result_make = '\n'.join([ result_make = '\n'.join([
@ -96,15 +95,12 @@ def create_build_archive(l_irp_o, l_usr_o_wo_main, l_ext_o, l_irp_sup_o, ninja=T
list_of_object = ' '.join(l_irp_o + l_usr_o_wo_main + l_ext_o + l_irp_sup_o) list_of_object = ' '.join(l_irp_o + l_usr_o_wo_main + l_ext_o + l_irp_sup_o)
result_ninja = '\n'.join([ result_ninja = '\n'.join(
"build {lib}: archive_{irp_id} {list_of_object}", ["build {lib}: archive_{irp_id} {list_of_object}", " short_out = {short_lib}", ""])
" short_out = {short_lib}",
""])
result_make = '\n'.join([ result_make = '\n'.join([
"{lib}: {list_of_object}", "{lib}: {list_of_object}", '\t@printf "Archive: {short_lib}\\n"', "\t@$(AR) cr $@ $^", ""
'\t@printf "Archive: {short_lib}\\n"', ])
"\t@$(AR) cr $@ $^", ""])
result = result_ninja if ninja else result_make result = result_ninja if ninja else result_make
return result.format(**locals()) return result.format(**locals())
@ -125,7 +121,8 @@ def create_build_link(t, l_irp_m, l_usr_m, l_ext_m, ninja=True):
basename = os.path.basename(filename) basename = os.path.basename(filename)
if basename != progname: if basename != progname:
from util import logger from util import logger
logger.info('program-name `{0}` != file-name `{1}` (using file-name for now...)'.format(progname,basename)) logger.info('program-name `{0}` != file-name `{1}` (using file-name for now...)'.format(
progname, basename))
target = dress(filename, in_root=True) target = dress(filename, in_root=True)
short_target = filename short_target = filename
@ -138,14 +135,13 @@ def create_build_link(t, l_irp_m, l_usr_m, l_ext_m, ninja=True):
result_ninja = '\n'.join([ result_ninja = '\n'.join([
"build {target}: link_{irp_id} {target_o} {irp_lib} | {list_of_module}", "build {target}: link_{irp_id} {target_o} {irp_lib} | {list_of_module}",
" short_out = {short_target}", " short_out = {short_target}", ""
""]) ])
result_make = '\n'.join([ result_make = '\n'.join([
"{target}:{target_o} {irp_lib} | {list_of_module}", "{target}:{target_o} {irp_lib} | {list_of_module}", '\t@printf "Link: {short_target}\\n"',
'\t@printf "Link: {short_target}\\n"', "\t@$(FC) $^ $(LIB) -o $@", ""
"\t@$(FC) $^ $(LIB) -o $@", ])
""])
result = result_ninja if ninja else result_make result = result_ninja if ninja else result_make
@ -186,10 +182,10 @@ def create_build_compile(t, l_module, l_ext_modfile=[], ninja=True):
# Expensive and stupid. We can create a dict to do the loockup only once # Expensive and stupid. We can create a dict to do the loockup only once
for m in t.needed_modules_usr: for m in t.needed_modules_usr:
# m is name # m is name
for x in l_module: for x in l_module:
if m in x.gen_mod and x.filename != t.filename: if m in x.gen_mod and x.filename != t.filename:
needed_modules.append("%s.irp.o" % x.filename) needed_modules.append("%s.irp.o" % x.filename)
from util import uniquify from util import uniquify
needed_modules = uniquify(needed_modules) needed_modules = uniquify(needed_modules)
@ -206,7 +202,7 @@ def create_build_compile(t, l_module, l_ext_modfile=[], ninja=True):
target_module_F90 = dress(short_target_module_F90) target_module_F90 = dress(short_target_module_F90)
needed_modules_irp += [target_module_o] needed_modules_irp += [target_module_o]
list_of_modules = ' '.join(map(dress, needed_modules)) list_of_modules = ' '.join(map(dress, needed_modules))
list_of_modules_irp = ' '.join(map(dress, needed_modules_irp)) list_of_modules_irp = ' '.join(map(dress, needed_modules_irp))
inline_include = True inline_include = True
@ -217,27 +213,23 @@ def create_build_compile(t, l_module, l_ext_modfile=[], ninja=True):
else: else:
#The include have already by included #The include have already by included
list_of_includes = ' ' list_of_includes = ' '
l_build = [ l_build = [
"build {target_o}: compile_fortran_{irp_id} {target_F90} | {list_of_includes} {list_of_modules} {list_of_modules_irp}", "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_in = {short_target_F90}", " short_out = {short_target}", ""
" short_out = {short_target}",
""
] ]
l_build_make = [ l_build_make = [
"{target_o}: {target_F90} | {list_of_includes} {list_of_modules} {list_of_modules_irp}", "{target_o}: {target_F90} | {list_of_includes} {list_of_modules} {list_of_modules_irp}",
'\t@printf "F: {short_target_F90} -> {short_target}\\n"', '\t@printf "F: {short_target_F90} -> {short_target}\\n"', "\t@$(FC) $(FCFLAGS) -c $^ -o $@",
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", "" ""
] ]
# No need of module when compiling the irp_module. # No need of module when compiling the irp_module.
if t.has_irp_module: if t.has_irp_module:
l_build += [ l_build += [
"build {target_module_o}: compile_fortran_{irp_id} {target_module_F90} | {list_of_includes} {list_of_modules} ", "build {target_module_o}: compile_fortran_{irp_id} {target_module_F90} | {list_of_includes} {list_of_modules} ",
" short_in = {short_target_module_F90}", " short_in = {short_target_module_F90}", " short_out = {short_target_module_o}", ""
" short_out = {short_target_module_o}",
""
] ]
l_build_make += [ l_build_make += [
@ -250,7 +242,7 @@ def create_build_compile(t, l_module, l_ext_modfile=[], ninja=True):
return '\n'.join(l_cur).format(**locals()) return '\n'.join(l_cur).format(**locals())
def create_build_remaining(f,ninja): def create_build_remaining(f, ninja):
""" """
Create the build command for the remaining file f. f is a file name (str). Create the build command for the remaining file f. f is a file name (str).
""" """
@ -271,108 +263,55 @@ def create_build_remaining(f,ninja):
if extension.lower() in ['f', 'f90']: if extension.lower() in ['f', 'f90']:
result = ["build {target_o}: compile_fortran_{irp_id} {target_i}"] result = ["build {target_o}: compile_fortran_{irp_id} {target_i}"]
result_make = [
'{target_o}: {target_i}', '\t@printf "F: {short_target_o} -> {short_target_i}\\n"',
"\t@$(FC) $(FCFLAGS) -c $^ -o $@", ""
]
elif extension.lower() in ['c']: elif extension.lower() in ['c']:
result = ["build {target_o}: compile_c_{irp_id} {target_i}"] result = ["build {target_o}: compile_c_{irp_id} {target_i}"]
elif extension.lower() in ['cxx', 'cpp']: elif extension.lower() in ['cxx', 'cpp']:
result = ["build {target_o}: compile_cxx_{irp_id} {target_i}"] result = ["build {target_o}: compile_cxx_{irp_id} {target_i}"]
result += [" short_in = {short_target_i}", " short_out = {short_target_o}", ""] result += [" short_in = {short_target_i}", " short_out = {short_target_o}", ""]
return '\n'.join(result).format(**locals())
result_final = result if ninja else result_make
return '\n'.join(result_final).format(**locals())
def create_makefile(d_flags,d_var,irpf90_flags,ninja=True): def create_makefile(d_flags, d_var, irpf90_flags, ninja=True):
result = ["IRPF90= irpf90", d = {'BUILD_SYSTEM': 'ninja' if ninja else 'make',
"IRPF90FLAGS= %s" % irpf90_flags, 'irpf90_flags': 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",
"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"]
d.update(d_flags)
d.update(d_var)
import util import util
data = '%s\n' % '\n'.join(result) str_ = util.ashes_env.render('general.make', d)
util.lazy_write_file('Makefile',data,conservative=True) util.lazy_write_file('Makefile', str_, conservative=True)
def create_make_all_clean(l_main): def create_make_all_clean(l_main):
# #
'''Create the ALL and CLEAN target of Makefile '''Create the ALL and CLEAN target of Makefile
Note: Portability doesn't mater. -delete is maybe not posix Note: Portability doesn't mater. -delete is maybe not posix
but -exec rm {} + is far more ugly! but -exec rm {} + is far more ugly!
''' '''
l_executable =' '.join(dress( t.filename, in_root=True) for t in l_main) l_executable = ' '.join(dress(t.filename, in_root=True) for t in l_main)
output = [".PHONY : all", output = [
"all: {l_executable}", ".PHONY : all", "all: {l_executable}", "", ".PHONY: clean", "clean:",
"", '\tfind . -type f \( -name "*.o" -o -name "*.mod" \) -delete; rm -f {l_executable} --'
".PHONY: clean", ""
"clean:", ]
'\tfind . -type f \( -name "*.o" -o -name "*.mod" \) -delete; rm -f {l_executable} --'
""] return ['\n'.join(output).format(**locals())]
return [ '\n'.join(output).format(**locals())]
def create_var_and_rule(d_flags, ninja): def create_var_and_rule(d_flags, ninja):
@ -383,59 +322,49 @@ def create_var_and_rule(d_flags, ninja):
# Rules # Rules
t = [ t = [
"rule compile_fortran_{irp_id}", "rule compile_fortran_{irp_id}", " command = $FC $FCFLAGS -c $in -o $out",
" command = $FC $FCFLAGS -c $in -o $out", " description = F : $short_in -> $short_out", "", "rule compile_c_{irp_id}",
" description = F : $short_in -> $short_out",
"",
"rule compile_c_{irp_id}",
" command = $CC $CFLAGS -c $in -o $out", " command = $CC $CFLAGS -c $in -o $out",
" description = C : $short_in -> $short_out", " description = C : $short_in -> $short_out", "", "rule compile_cxx_{irp_id}",
"",
"rule compile_cxx_{irp_id}",
" command = $CXX $CXXFLAGS -c $in -o $out", " command = $CXX $CXXFLAGS -c $in -o $out",
" description = C++ : $short_in -> $short_out", " description = C++ : $short_in -> $short_out", "", "rule archive_{irp_id}",
"", " command = $AR cr $out $in", " description = Archive: $short_out", "",
"rule archive_{irp_id}", "rule link_{irp_id}", " command = $FC $FCFLAGS $in $LIB -o $out",
" command = $AR cr $out $in", " description = Link: $short_out", ""
" 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)] output += ['\n'.join(t).format(irp_id=irpf90_t.irp_id, **d_flags)]
return output return output
# Environment variables # Environment variables
d_default = { d_default = {
"FC": "gfortran", "FC": "gfortran",
"FCFLAGS": "-O2", "FCFLAGS": "-O2",
"AR": "ar", "AR": "ar",
"RANLIB": " ranlib", "RANLIB": " ranlib",
"CC": "gcc", "CC": "gcc",
"CFLAGS": "-O2", "CFLAGS": "-O2",
"CXX": "g++", "CXX": "g++",
"CXXFLAGS": "-O2", "CXXFLAGS": "-O2",
"LIB": ""} "LIB": ""
}
d_flags = dict() d_flags = dict()
for k, v in d_default.iteritems(): for k, v in d_default.iteritems():
d_flags[k] = os.environ[k] if k in os.environ else v 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]) include_dir = ' ' + ' '.join(["-I %s" % (i) for i in command_line.include_dir])
d_var = dict() d_var = dict()
for k in ['SRC', 'OBJ']: for k in ['SRC', 'OBJ']:
d_var[k] = os.environ[k].split() if k in os.environ else [] d_var[k] = os.environ[k].split() if k in os.environ else []
def create_generalmakefile(ninja): def create_generalmakefile(ninja):
create_makefile(d_flags,d_var, include_dir,ninja) create_makefile(d_flags, d_var, include_dir, ninja)
def run(d_module, ninja): def run(d_module, ninja):
#(Dict[str,Module],bool) -> str #(Dict[str,Module],bool) -> str
@ -476,7 +405,7 @@ def run(d_module, ninja):
l_irp_sup_o = ["irp_touches.irp.o"] l_irp_sup_o = ["irp_touches.irp.o"]
l_irp_sup_s = ["irp_touches.irp.F90"] l_irp_sup_s = ["irp_touches.irp.F90"]
if command_line.do_assert: if command_line.do_debug or command_line.do_assert:
l_irp_sup_o += ["irp_stack.irp.o"] l_irp_sup_o += ["irp_stack.irp.o"]
l_irp_sup_s += ["irp_stack.irp.F90"] l_irp_sup_s += ["irp_stack.irp.F90"]
@ -484,9 +413,13 @@ def run(d_module, ninja):
l_irp_sup_o += ["irp_locks.irp.o"] l_irp_sup_o += ["irp_locks.irp.o"]
l_irp_sup_s += ["irp_locks.irp.F90"] l_irp_sup_s += ["irp_locks.irp.F90"]
if command_line.do_profile or command_line.do_codelet:
l_irp_sup_o += ["irp_rdtsc.o"]
l_irp_sup_s += ["irp_rdtsc.c"]
if command_line.do_profile: if command_line.do_profile:
l_irp_sup_o += ["irp_profile.irp.o", "irp_rdtsc.o"] l_irp_sup_o += ["irp_profile.irp.o"]
l_irp_sup_s += ["irp_profile.irp.F90", "irp_rdtsc.c"] l_irp_sup_s += ["irp_profile.irp.F90"]
l_irp_sup_o = map(dress, l_irp_sup_o) l_irp_sup_o = map(dress, l_irp_sup_o)
l_irp_sup_s = map(dress, l_irp_sup_s) l_irp_sup_s = map(dress, l_irp_sup_s)
@ -515,7 +448,7 @@ def run(d_module, ninja):
for m in l_mod: for m in l_mod:
output.append(create_build_compile(m, l_mod, l_ext_m, ninja)) output.append(create_build_compile(m, l_mod, l_ext_m, ninja))
output.append(create_build_touches(l_irp_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 # 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)) output.append(create_build_archive(l_irp_o, l_usr_o_wo_main, l_ext_o, l_irp_sup_o, ninja))
@ -524,13 +457,13 @@ def run(d_module, ninja):
output.append(create_build_link(i, l_irp_m, l_usr_m, l_ext_m, ninja)) output.append(create_build_link(i, l_irp_m, l_usr_m, l_ext_m, ninja))
# Remaining files # Remaining files
for i in l_irp_sup_s[1:]+l_ext_s: for i in l_irp_sup_s[1:] + l_ext_s:
output.append(create_build_remaining(i, ninja)) output.append(create_build_remaining(i, ninja))
filename = os.path.join(irpdir, "build.ninja" if ninja else "build.make") filename = os.path.join(irpdir, "build.ninja" if ninja else "build.make")
data = '%s\n' % '\n\n'.join(output) data = '%s\n' % '\n\n'.join(output)
import util import util
util.lazy_write_file(filename,data,touch=True) util.lazy_write_file(filename, data, touch=True)
return return

View File

@ -27,8 +27,9 @@
from command_line import command_line from command_line import command_line
import irpf90_t import irpf90_t
def run(): def run():
template = """ template = """
program codelet_%(name)s program codelet_%(name)s
implicit none implicit none
integer :: i integer :: i
@ -58,12 +59,11 @@ end
""" """
name, NMAX, precondition, filename = command_line.codelet name, NMAX, precondition, filename = command_line.codelet
if precondition is None: if precondition is None:
precondition = "" precondition = ""
else: else:
precondition = "PROVIDE "+precondition precondition = "PROVIDE " + precondition
from util import lazy_write_file
lazy_write_file(filename,template%locals())
from util import lazy_write_file
lazy_write_file(filename, template % locals())

View File

@ -24,11 +24,7 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
try: from lib.manager import irpy
import irpy
except:
import lib_irpy as irpy
import getopt, sys import getopt, sys
from version import version from version import version
@ -36,124 +32,150 @@ import re
description = "IRPF90 Fortran preprocessor." description = "IRPF90 Fortran preprocessor."
options = {} options = {}
options['a'] = [ 'assert' , 'Activates ASSERT statements. If absent, remove ASSERT statements.', 0 ] options['a'] = ['assert', 'Activates ASSERT statements. If absent, remove ASSERT statements.', 0]
options['c'] = [ 'codelet' , 'entity:NMAX or entity:precondition:NMAX : Generate a codelet to profile a provider running NMAX times', 1 ] options['c'] = [
options['C'] = [ 'coarray' , 'All providers are coarrays', 0 ] 'codelet',
options['d'] = [ 'debug' , 'Activates debug. The name of the current subroutine/function/provider will be printed on the standard output when entering or exiting a routine, as well as the CPU time passed inside the routine.', 0 ] 'entity:NMAX or entity:precondition:NMAX : Generate a codelet to profile a provider running NMAX times',
options['D'] = [ 'define' , 'Defines a variable identified by the IRP_IF statements.', 1 ] 1
options['g'] = [ 'profile' , 'Activates profiling of the code.', 0 ] ]
options['h'] = [ 'help' , 'Print this help', 0 ] options['C'] = ['coarray', 'All providers are coarrays', 0]
options['I'] = [ 'include' , 'Include directory', 1 ] options['d'] = [
options['j'] = [ 'ninja' , 'Use Ninja instead of make', 0 ] 'debug',
options['i'] = [ 'init' , 'Initialize current directory. Creates a default Makefile and the temporary working directories.', 0 ] 'Activates debug. The name of the current subroutine/function/provider will be printed on the standard output when entering or exiting a routine, as well as the CPU time passed inside the routine.',
options['l'] = [ 'align' , 'Align arrays using compiler directives and sets the $IRP_ALIGN variable. For example, --align=32 aligns all arrays on a 32 byte boundary.', 1 ] 0
options['m'] = [ 'memory' , 'Print memory allocations/deallocations.', 0 ] ]
options['n'] = [ 'inline' , '<all|providers|builders> : Force inlining of providers or builders', 1 ] options['D'] = ['define', 'Defines a variable identified by the IRP_IF statements.', 1]
options['o'] = [ 'checkopt' , 'Shows where optimization may be required', 0 ] options['g'] = ['profile', 'Activates profiling of the code.', 0]
options['p'] = [ 'preprocess' , 'Prints a preprocessed file to standard output. Useful for debugging files containing shell scripts.', 1 ] options['h'] = ['help', 'Print this help', 0]
options['r'] = [ 'no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0 ] options['I'] = ['include', 'Include directory', 1]
options['s'] = [ 'substitute' , 'Substitute values in do loops for generating specific optimized code.', 1 ] options['j'] = ['ninja', 'Use Ninja instead of make', 0]
options['t'] = [ 'touch' , 'Display which entities are touched when touching the variable given as an argument.', 1 ] options['i'] = [
options['v'] = [ 'version' , 'Prints version of irpf90', 0 ] 'init',
options['w'] = [ 'warnings' , 'Activate Warnings', 0 ] 'Initialize current directory. Creates a default Makefile and the temporary working directories.',
options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ] 0
options['G'] = [ 'graph' , 'Print the dependecy-graph of the entities (dots format)', 0 ] ]
options['l'] = [
'align',
'Align arrays using compiler directives and sets the $IRP_ALIGN variable. For example, --align=32 aligns all arrays on a 32 byte boundary.',
1
]
options['m'] = ['memory', 'Print memory allocations/deallocations.', 0]
options['n'] = ['inline', '<all|providers|builders> : Force inlining of providers or builders', 1]
options['o'] = ['checkopt', 'Shows where optimization may be required', 0]
options['p'] = [
'preprocess',
'Prints a preprocessed file to standard output. Useful for debugging files containing shell scripts.',
1
]
options['r'] = ['no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0]
options['s'] = [
'substitute', 'Substitute values in do loops for generating specific optimized code.', 1
]
options['t'] = [
'touch', 'Display which entities are touched when touching the variable given as an argument.',
1
]
options['v'] = ['version', 'Prints version of irpf90', 0]
options['w'] = ['warnings', 'Activate Warnings', 0]
options['z'] = ['openmp', 'Activate for OpenMP code', 0]
options['G'] = ['graph', 'Print the dependecy-graph of the entities (dots format)', 0]
options['T'] = ['Task', 'Auto-parallelism ', 0]
class CommandLine(object): class CommandLine(object):
def __init__(self):
global options
self._opts = None
self.argv = list(sys.argv)
self.executable_name = self.argv[0]
def __init__(self): @irpy.lazy_property
global options def defined(self):
self._opts = None return [a for o, a in self.opts if o in ["-D", '--' + options['D'][0]]]
self.argv = list(sys.argv)
self.executable_name = self.argv[0]
@irpy.lazy_property @irpy.lazy_property
def defined(self): def graph(self):
return [ a for o,a in self.opts if o in [ "-D", '--'+options['D'][0] ] ] return next((a.split() for o, a in self.opts if o in ["-G", '--' + options['G'][0]]), [])
@irpy.lazy_property @irpy.lazy_property
def graph(self): def include_dir(self):
return next((a.split() for o,a in self.opts if o in ["-G", '--'+options['G'][0] ]),[]) l = []
for o, a in self.opts:
@irpy.lazy_property if o in ["-I", '--' + options['I'][0]]:
def include_dir(self): if len(a) < 1:
self._include_dir = [] print "Error: -I option needs a directory"
for o,a in self.opts: if a[-1] != '/':
if o in [ "-I", '--'+options['I'][0] ]: a = a + '/'
if len(a) < 1: l.append(a)
print "Error: -I option needs a directory" return l
if a[-1] != '/':
a = a+'/'
self._include_dir.append(a)
return self._include_dir
@irpy.lazy_property
def inline(self):
return next( (a for o,a in self.opts if o in [ "-n", '--'+options['n'][0] ]),'')
@irpy.lazy_property @irpy.lazy_property
def substituted(self): def inline(self):
self._substituted = {} return next((a for o, a in self.opts if o in ["-n", '--' + options['n'][0]]), '')
for o,a in self.opts:
if o in [ "-s", '--'+options['s'][0] ]:
k, v = a.split(':')
v_re = re.compile(r"(\W)(%s)(\W.*$|$)"%k.strip())
self._substituted[k] = [v, v_re]
return self._substituted
@irpy.lazy_property @irpy.lazy_property
def codelet(self): def substituted(self):
for o,a in self.opts: self._substituted = {}
if o in [ "-c", '--'+options['c'][0] ]: for o, a in self.opts:
buffer = a.split(':') if o in ["-s", '--' + options['s'][0]]:
filename = 'codelet_'+buffer[0]+'.irp.f' k, v = a.split(':')
if len(buffer) == 2: v_re = re.compile(r"(\W)(%s)(\W.*$|$)" % k.strip())
return [buffer[0], int(buffer[1]), None, filename] self._substituted[k] = [v, v_re]
elif len(buffer) == 3: return self._substituted
return [buffer[0], int(buffer[2]), buffer[1], filename]
else: @irpy.lazy_property
print """ def codelet(self):
for o, a in self.opts:
if o in ["-c", '--' + options['c'][0]]:
buffer = a.split(':')
filename = 'codelet_' + buffer[0] + '.irp.f'
if len(buffer) == 2:
return [buffer[0], int(buffer[1]), None, filename]
elif len(buffer) == 3:
return [buffer[0], int(buffer[2]), buffer[1], filename]
else:
print """
Error in codelet definition. Use: Error in codelet definition. Use:
--codelet=provider:NMAX --codelet=provider:NMAX
or or
--codelet=provider:precondition:NMAX --codelet=provider:precondition:NMAX
""" """
sys.exit(1) sys.exit(1)
@irpy.lazy_property @irpy.lazy_property
def preprocessed(self): def preprocessed(self):
return [a for o,a in self.ops if o in [ "-p", '--'+options['p'][0] ] ] return [a for o, a in self.ops if o in ["-p", '--' + options['p'][0]]]
@irpy.lazy_property @irpy.lazy_property
def touched(self): def touched(self):
return [a for o,a in self.ops if o in [ "-t", '--'+options['t'][0] ] ] return [a for o, a in self.ops if o in ["-t", '--' + options['t'][0]]]
@irpy.lazy_property @irpy.lazy_property
def align(self): def align(self):
return next( (a for o,a in self.opts if o in [ "-l", '--'+options['l'][0] ]),'1') return next((a for o, a in self.opts if o in ["-l", '--' + options['l'][0]]), '1')
@irpy.lazy_property @irpy.lazy_property
def coarray(self): def coarray(self):
return any(o for o,a in self.opts if o in [ "-C", '--'+options['C'][0] ]) return any(o for o, a in self.opts if o in ["-C", '--' + options['C'][0]])
@irpy.lazy_property @irpy.lazy_property
def warnings(self): def warnings(self):
return any(o for o,a in self.opts if o in [ "-W", '--'+options['W'][0] ]) return any(o for o, a in self.opts if o in ["-W", '--' + options['W'][0]])
@irpy.lazy_property @irpy.lazy_property
def openmp(self): def openmp(self):
return any(o for o,a in self.opts if o in [ "-z", '--'+options['z'][0] ]) return any(o for o, a in self.opts if o in ["-z", '--' + options['z'][0]])
@irpy.lazy_property @irpy.lazy_property
def ninja(self): def ninja(self):
return any(o for o,a in self.opts if o in [ "-j", '--'+options['j'][0] ]) return any(o for o, a in self.opts if o in ["-j", '--' + options['j'][0]])
@irpy.lazy_property @irpy.lazy_property
def directives(self): def directives(self):
return not(any(o for o,a in self.opts if o in [ "-r", '--'+options['r'][0] ])) return not (any(o for o, a in self.opts if o in ["-r", '--' + options['r'][0]]))
def usage(self): def usage(self):
t = """ t = """
$EXE - $DESCR $EXE - $DESCR
Usage: Usage:
@ -161,37 +183,38 @@ Usage:
Options: Options:
""" """
t = t.replace("$EXE",self.executable_name) t = t.replace("$EXE", self.executable_name)
t = t.replace("$DESCR",description) t = t.replace("$DESCR", description)
print t print t
print_options() print_options()
print "" print ""
print "Version : ", version print "Version : ", version
print "" print ""
def opts(self): def opts(self):
if self._opts is None: if self._opts is None:
optlist = ["",[]] optlist = ["", []]
for o in options: for o in options:
b = [o]+options[o] b = [o] + options[o]
if b[3] == 1: if b[3] == 1:
b[0] = b[0]+":" b[0] = b[0] + ":"
b[1] = b[1]+"=" b[1] = b[1] + "="
optlist[0] += b[0] optlist[0] += b[0]
optlist[1] += [b[1]] optlist[1] += [b[1]]
try: try:
self._opts, args = getopt.getopt(self.argv[1:], optlist[0], optlist[1]) self._opts, args = getopt.getopt(self.argv[1:], optlist[0], optlist[1])
except getopt.GetoptError, err: except getopt.GetoptError, err:
# print help information and exit: # print help information and exit:
self.usage() self.usage()
print str(err) # will print something like "option -a not recognized" print str(err) # will print something like "option -a not recognized"
sys.exit(2) sys.exit(2)
return self._opts return self._opts
opts = property(fget=opts)
opts = property(fget=opts)
t = """
t = """
def do_$LONG(self): def do_$LONG(self):
if '_do_$LONG' not in self.__dict__: if '_do_$LONG' not in self.__dict__:
self._do_$LONG = False self._do_$LONG = False
@ -202,28 +225,35 @@ def do_$LONG(self):
return self._do_$LONG return self._do_$LONG
do_$LONG = property(fget=do_$LONG) do_$LONG = property(fget=do_$LONG)
""" """
for short in options: for short in options:
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):
return not(any( (self.do_version, self.do_help, self.do_preprocess, self.do_touch, self.do_init)))
@irpy.lazy_property
def do_run(self):
return not (any(
(self.do_version, self.do_help, self.do_preprocess, self.do_touch, self.do_init)))
# @irpy.lazy_property
# def do_Task(self):
# return True
command_line = CommandLine() command_line = CommandLine()
def print_options(): def print_options():
keys = options.keys() keys = options.keys()
keys.sort() keys.sort()
import subprocess import subprocess
for k in keys: for k in keys:
description = options[k][1] description = options[k][1]
p1 = subprocess.Popen(["fold", "-s", "-w", "40"],stdout=subprocess.PIPE,stdin=subprocess.PIPE) p1 = subprocess.Popen(
description = p1.communicate(description)[0] ["fold", "-s", "-w", "40"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
description = description.replace('\n','\n'.ljust(27)) description = p1.communicate(description)[0]
print ("-%s, --%s"%(k,options[k][0])).ljust(25), description+'\n' description = description.replace('\n', '\n'.ljust(27))
print "\n" print("-%s, --%s" % (k, options[k][0])).ljust(25), description + '\n'
print "\n"
if __name__ == '__main__': if __name__ == '__main__':
print_options() print_options()

View File

@ -27,9 +27,10 @@
from entity import Entity from entity import Entity
from routine import Routine from routine import Routine
from irpf90_t import mandir from irpf90_t import mandir
from util import parmap, build_dim,lazy_write_file from util import parmap, build_dim, lazy_write_file
import os import os
def do_print_short(entity): def do_print_short(entity):
assert type(entity) == Entity assert type(entity) == Entity
str_ = "{0:<35} : {1:<30} :: {2:<25} {3}".format(entity.prototype.filename[0], str_ = "{0:<35} : {1:<30} :: {2:<25} {3}".format(entity.prototype.filename[0],
@ -56,7 +57,7 @@ def process_deps(l):
def process_types(entity_input, d_entity): def process_types(entity_input, d_entity):
assert type(entity_input) == Entity assert type(entity_input) == Entity
l_name = [entity_input.name] + entity_input.others_entity_name l_name = entity_input.l_name
l_entity = [d_entity[name] for name in l_name] l_entity = [d_entity[name] for name in l_name]
l = [ "{0}\t:: {1}\t{2}".format(entity.type, name, build_dim(entity.dim) ) l = [ "{0}\t:: {1}\t{2}".format(entity.type, name, build_dim(entity.dim) )
@ -107,7 +108,6 @@ def do_print(entity, d_entity):
lazy_write_file("%s%s.l" % (mandir, name), '%s\n' % str_) lazy_write_file("%s%s.l" % (mandir, name), '%s\n' % str_)
###################################################################### ######################################################################
def do_print_subroutines(sub): def do_print_subroutines(sub):
assert type(sub) == Routine assert type(sub) == Routine
@ -164,8 +164,8 @@ def run(d_entity, d_routine):
l_subs = d_routine.values() l_subs = d_routine.values()
l_data_to_write = [("%s.l" % os.path.join(mandir, s.name), do_print_subroutines(s)) for s in l_subs] l_data_to_write = [("%s.l" % os.path.join(mandir, s.name), do_print_subroutines(s))
for s in l_subs]
def worker(l): def worker(l):
filename, text = l filename, text = l

View File

@ -28,10 +28,7 @@ from irpf90_t import *
from util import * from util import *
from command_line import command_line from command_line import command_line
import sys import sys
try: from lib.manager import irpy
import irpy
except:
import lib_irpy as irpy
class Entity(object): class Entity(object):
@ -64,7 +61,6 @@ class Entity(object):
self.comm_world = comm_world self.comm_world = comm_world
# ~ # ~ # ~ # ~ # ~ # ~
# G l o b a l P r o p e r t y # G l o b a l P r o p e r t y
# ~ # ~ # ~ # ~ # ~ # ~
@ -97,7 +93,6 @@ class Entity(object):
d[type(line)] += [(i, line)] d[type(line)] += [(i, line)]
return d 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 # M u l t i p l e P r o v i d e r H a n d l e r
# ~ # ~ # ~ # ~ # ~ # ~
@ -105,16 +100,15 @@ class Entity(object):
def is_main(self): def is_main(self):
# () -> bool # () -> bool
'''Check if this Entity is the main one '''Check if this Entity is the main one
Exemple: Exemple:
BEGIN_PROVIDER [pi, double precision] & BEGIN_PROVIDER [pi, double precision] &
BEGIN_PROVIDER [e, double preision] BEGIN_PROVIDER [e, double preision]
return True for 'pi' and False for 'e' return True for 'pi' and False for 'e'
''' '''
return self.name == self.same_as return self.name == self.same_as
@irpy.lazy_property @irpy.lazy_property
def prototype(self): def prototype(self):
# () -> Line # () -> Line
@ -128,21 +122,25 @@ class Entity(object):
''' '''
d = self.d_type_lines d = self.d_type_lines
return next(line for _,line in d[Begin_provider]+d[Cont_provider] if line.filename[1] == self.name) return next(line for _, line in d[Begin_provider] + d[Cont_provider]
if line.filename[1] == self.name)
@irpy.lazy_property @irpy.lazy_property
def others_entity_name(self): def l_name(self):
# () -> List[str]
d = self.d_type_lines
return [line.filename[1] for _, line in d[Begin_provider] + d[Cont_provider]]
@irpy.lazy_property
def l_others_name(self):
# () -> List[str] # () -> List[str]
'''Extract the other entity-name defined''' '''Extract the other entity-name defined'''
d = self.d_type_lines return [name for name in self.l_name if not name == self.name]
return [line.filename[1] for _,line in d[Begin_provider]+d[Cont_provider] if not line.filename[1] == self.name]
@irpy.lazy_property @irpy.lazy_property
def doc(self): def doc(self):
# () -> List[str] # () -> List[str]
doc = [line.text.lstrip()[1:] for _,line in self.d_type_lines[Doc]] doc = [line.text.lstrip()[1:] for _, line in self.d_type_lines[Doc]]
if not doc: if not doc:
logger.warning("Entity '%s' is not documented" % (self.name)) logger.warning("Entity '%s' is not documented" % (self.name))
return doc return doc
@ -163,45 +161,36 @@ class Entity(object):
return any(self.d_entity[i].is_written for i in self.parents) return any(self.d_entity[i].is_written for i in self.parents)
@irpy.lazy_property @irpy.lazy_property
def writer(self): def io_er(self):
if not self.is_main: if not self.is_main:
result = [] result = []
else:
name = self.name from util import mangled
result = [ \ from util import ashes_env
"subroutine writer_%s(irp_num)"%(name), name = self.name
" use %s"%(self.fmodule),
" implicit none", d_template = {
" character*(*), intent(in) :: irp_num", 'name': name,
" logical :: irp_is_open", 'fmodule': self.fmodule,
" integer :: irp_iunit" ] 'same_as': self.same_as,
if command_line.do_debug: 'do_debug': command_line.do_debug,
length = len("writer_%s" % (self.name)) 'children': mangled(self.needs, self.d_entity),
result += [\ 'group_entity': [{
" character*(%d) :: irp_here = 'writer_%s'"%(length,name), 'name': n,
" call irp_enter(irp_here)" ] 'dim': build_dim(
result += [ \ self.d_entity[n].dim, colons=True)
" if (.not.%s_is_built) then"%(self.same_as), } for n in self.l_name]
" call provide_%s"%(self.same_as), }
" endif" ]
result += map(lambda x: " call writer_%s(irp_num)" % (x), self.needs) return ashes_env.render('ioer.f90', d_template).split('!TOKEN_SPLIT')
result += [ \
" irp_is_open = .True.", @irpy.lazy_property
" irp_iunit = 9", def reader(self):
" do while (irp_is_open)", return self.io_er[1].split('\n')
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)", @irpy.lazy_property
" enddo" ] def writer(self):
for n in [name] + self.others_entity_name: return self.io_er[0].split('\n')
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 @irpy.lazy_property_mutable
def is_read(self): def is_read(self):
@ -209,43 +198,8 @@ class Entity(object):
return any(self.d_entity[i].is_read for i in self.parents) return any(self.d_entity[i].is_read for i in self.parents)
@irpy.lazy_property @irpy.lazy_property
def reader(self): def is_source_touch(self):
if not self.is_main: return (Touch in self.d_type_lines or SoftTouch in self.d_type_lines)
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 @irpy.lazy_property_mutable
def is_self_touched(self): def is_self_touched(self):
@ -257,7 +211,7 @@ class Entity(object):
'''If any of the children is touched, the entity is touched''' '''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): if self.is_self_touched or any(self.d_entity[i].is_touched for i in self.children):
return True return True
return False return False
# ~ # ~ # ~ # ~ # ~ # ~
@ -268,21 +222,21 @@ class Entity(object):
def includes(self): def includes(self):
# () -> str # () -> str
'''Extract the name of include who need be to be include in this Entity''' '''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]] return [line.filename for _, line in self.d_type_lines[Include]]
@irpy.lazy_property @irpy.lazy_property
def uses(self): def uses(self):
'''Extract the name of module who are used in this Entity''' '''Extract the name of module who are used in this Entity'''
return [line.filename for _,line in self.d_type_lines[Use]] return [line.filename for _, line in self.d_type_lines[Use]]
@irpy.lazy_property @irpy.lazy_property
def calls(self): def calls(self):
'''Extract the name ofthe function called by the entity''' '''Extract the name ofthe function called by the entity'''
def extract_name(line): def extract_name(line):
return line.text.split('(', 1)[0].split()[1].lower() return line.text.split('(', 1)[0].split()[1].lower()
return [extract_name(line) for _,line in self.d_type_lines[Call] ] return [extract_name(line) for _, line in self.d_type_lines[Call]]
# ~ # ~ # ~ # ~ # ~ # ~
# Array Dimension # Array Dimension
@ -314,7 +268,6 @@ class Entity(object):
else: else:
return map(str.strip, x[1:-1].split(',')) return map(str.strip, x[1:-1].split(','))
@irpy.lazy_property @irpy.lazy_property
def allocate(self): def allocate(self):
# () -> List[Str] # () -> List[Str]
@ -323,11 +276,14 @@ class Entity(object):
return [] return []
else: else:
# We never go here # We never go here
return [var for var in self.others_entity_name + [self.name] if self.d_entity[var].dim] return [var for var in l_name if self.d_entity[var].dim]
# ~ # ~ # ~ # ~ # ~ # ~
# D e c l a r a t i o n # D e c l a r a t i o n
# ~ # ~ # ~ # ~ # ~ # ~
@irpy.lazy_property
def is_protected(self):
return self.text[0].lower.startswith('begin_provider_immu')
@irpy.lazy_property @irpy.lazy_property
def type(self): def type(self):
@ -337,7 +293,7 @@ class Entity(object):
type_ = self.prototype.text.split(',')[0].split('[')[1].strip() type_ = self.prototype.text.split(',')[0].split('[')[1].strip()
if not type_: if not type_:
logger.error( "Error in definition of %s." % (self.name)) logger.error("Error in definition of %s." % (self.name))
sys.exit(1) sys.exit(1)
if self.dim: if self.dim:
@ -346,29 +302,20 @@ class Entity(object):
return type_ return type_
@irpy.lazy_property @irpy.lazy_property
def header(self): def d_header(self):
# () -> List[str] # () -> List[str]
'''Compute all the code needed to inistanticant the entity''' '''Compute all the code needed to inistanticant the entity'''
import util
name = self.name d_template = {
str_ = " {type_} :: {name} {dim}".format(type_=self.type, name=name, dim=build_dim(self.dim, colons=True)) 'name': self.name,
'type': self.type,
if command_line.coarray: 'main': self.is_main,
if not self.dim: 'dim': build_dim(
str_ += " [*]" self.dim, colons=True),
else: 'protected': '\n'.join(self.allocater + self.builder) if self.is_protected else False
str_ += " [:]" }
return d_template
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 @irpy.lazy_property
@ -391,94 +338,38 @@ class Entity(object):
# ~ # ~ # ~ # ~ # ~ # ~
@irpy.lazy_property @irpy.lazy_property
def toucher(self): def d_touche_template(self):
# () -> List[str] # () -> List[str]
'''Fabric the f90 routine who handle the cache invalidation''' '''Fabric the f90 routine who handle the cache invalidation'''
# Only one by EntityColleciton # Only one by EntityColleciton
if not self.is_main: if not self.is_main:
return [] return {}
parents = self.parents from util import mangled
name = self.name
result = ["subroutine touch_%s" % (name)] return {
'name': self.name,
result += build_use(parents+[name],self.d_entity) 'l_module':
result.append(" implicit none") [n for n in build_use(
self.parents + [self.name], self.d_entity, use=False)],
if command_line.do_debug: 'l_ancestor': [n for n in mangled(self.parents, self.d_entity)]
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 @irpy.lazy_property
def free(self): def free(self):
# () -> List[ str ] # () -> List[ str ]
'''Compute an part of a subroutine used to free a variable''' '''Compute an part of a subroutine used to free a variable'''
name = self.name name = self.name
result = ["!", result = ["!", "! >>> FREE %s" % (name), " %s_is_built = .False." % (self.same_as)]
"! >>> FREE %s" % (name),
" %s_is_built = .False." % (self.same_as)]
if self.dim: if self.dim:
result += [ result += [" if (allocated(%s)) then" % (name), " deallocate (%s)" % (name)]
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name)]
if command_line.do_memory: if command_line.do_memory:
result += " print *, 'Deallocating %s'"%(name) result += " print *, 'Deallocating %s'" % (name)
result += [" endif"] result += [" endif"]
@ -494,130 +385,56 @@ class Entity(object):
if not self.is_main: if not self.is_main:
return [] return []
from util import mangled
import util
name = self.name name = self.name
same_as = self.same_as l_module = [x for x in build_use([self.name] + self.to_provide, self.d_entity, use=False)]
l_children = [x for x in mangled(self.to_provide, self.d_entity)]
def dimsize(x): l_entity = [self.d_entity[n] for n in self.l_name]
# (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() l = ashes_env.render('provider.f90', {
b1_is_digit = b1.replace('-', '').isdigit() 'name': name,
'l_module': l_module,
'l_children_static': l_children,
'do_debug': command_line.do_debug,
'do_openmp': command_line.do_openmp,
'do_task': command_line.do_Task,
'do_corray': command_line.do_coarray,
'dim': ','.join(self.dim),
'l_entity': [{
'name': i.name,
'dim': ','.join(i.dim)
} for i in l_entity]
})
return [i for i in l.split('\n') if i.strip()]
if b0_is_digit and b1_is_digit: @irpy.lazy_property
size = str(int(b1) - int(b0) + 1) def allocater(self):
elif b0_is_digit: from util import mangled
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 import util
name = self.name
l_module = [x for x in build_use([self.name] + self.to_provide, self.d_entity, use=False)]
if self.is_protected:
l_module.remove(self.fmodule)
def build_alloc(name): l_dim = [{'name': name, 'rank': i + 1, 'value': dimsize(k)} for i, k in enumerate(self.dim)]
var = self.d_entity[name] l = ashes_env.render('allocater.f90', {
if var.dim == []: 'name': name,
return [] 'l_module': l_module,
'do_debug': command_line.do_debug,
'do_corray': command_line.do_coarray,
'do_memory': command_line.do_memory,
'dim': ','.join(self.dim),
'l_dim': l_dim
})
return [i for i in l.split('\n') if i.strip()]
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 @irpy.lazy_property
def builder(self): def builder(self):
if not self.is_main: if not self.is_main:
@ -651,6 +468,7 @@ class Entity(object):
line_prototype.filename))) line_prototype.filename)))
for vars, line in ps_text[begin + 1:end]: for vars, line in ps_text[begin + 1:end]:
text.append((vars, line)) text.append((vars, line))
text += map(lambda x: ([], Simple_line(line.i, x, line.filename)), text += map(lambda x: ([], Simple_line(line.i, x, line.filename)),
build_call_provide(vars, self.d_entity)) build_call_provide(vars, self.d_entity))
@ -665,13 +483,19 @@ class Entity(object):
# Add the use statement # Add the use statement
result += ["subroutine bld_%s" % (self.name)] result += ["subroutine bld_%s" % (self.name)]
result += build_use([self.name] + self.needs, self.d_entity)
l_use = build_use([self.name] + self.needs, self.d_entity, use=False)
if self.is_protected:
l_use.remove(self.fmodule)
result += ['USE %s' % n for n in l_use]
import parsed_text import parsed_text
# Move the variable to top, and add the text # Move the variable to top, and add the text
parsed_text.move_to_top_list(text, [Declaration, Implicit, Use]) 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))) result.extend(line.text for _, line in text
if not isinstance(line, (Begin_doc, End_doc, Doc, Cont_provider)))
if command_line.do_profile: if command_line.do_profile:
result += [ result += [
@ -689,6 +513,11 @@ class Entity(object):
#Set by parsed_text.build_needs(...) #Set by parsed_text.build_needs(...)
raise AttributeError raise AttributeError
@irpy.lazy_property_mutable
def needed_by(self):
#Set by parsed_text.build_needs(...)
return []
@irpy.lazy_property @irpy.lazy_property
def children(self): def children(self):
@ -708,16 +537,10 @@ class Entity(object):
########################################################## ##########################################################
@irpy.lazy_property @irpy.lazy_property
def parents(self): def parents(self):
if not self.is_main:
return []
result = [] result = []
for x in self.needed_by: for x in self.needed_by:
result.append(x) result.append(x)
try: result += self.d_entity[x].parents
result += self.d_entity[x].parents
except RuntimeError:
pass # Exception will be checked after
result = OrderedUniqueList(result) result = OrderedUniqueList(result)
if self.name in result: if self.name in result:

View File

@ -1,260 +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 util
from command_line import command_line
do_assert = command_line.do_assert
do_debug = command_line.do_debug
do_openmp = command_line.do_openmp
do_memory = command_line.do_memory
import irpf90_t
FILENAME = irpf90_t.irpdir+"irp_stack.irp.F90"
def create():
txt = """
module irp_stack_mod
integer, parameter :: STACKMAX=1000
character*(128),allocatable :: irp_stack(:,:)
double precision,allocatable :: irp_cpu(:,:)
integer,allocatable :: stack_index(:)
logical :: alloc = .False.
integer :: nthread
character*(128) :: white = ''
end module
subroutine irp_enter(irp_where)
use irp_stack_mod
integer :: ithread
character*(*) :: irp_where
"""
if not do_openmp:
txt += """
ithread = 0
"""
else:
txt += """
integer, external :: omp_get_thread_num
integer, external :: omp_get_num_threads
ithread = omp_get_thread_num()
"""
txt += "$1"
if do_memory:
txt+="""
if (.not.alloc) then
"""
if do_openmp:
txt += """
!$OMP PARALLEL
!$OMP SINGLE
nthread = omp_get_num_threads()
!$OMP END SINGLE
!$OMP END PARALLEL
"""
else:
txt += """
nthread = 1
"""
txt += """
print *, 'Allocating irp_stack(' , STACKMAX , ',0:', nthread, ')'
print *, 'Allocating irp_cpu(' , STACKMAX , ',0:', nthread , ')'
print *, 'Allocating stack_index(0:', nthread, ')'
endif"""
txt +="""
$2
end subroutine
subroutine irp_enter_f(irp_where)
use irp_stack_mod
integer :: ithread
character*(*) :: irp_where
"""
if do_openmp:
txt += """
integer, external :: omp_get_thread_num
integer, external :: omp_get_num_threads
ithread = omp_get_thread_num()
"""
else:
txt += """
ithread = 0
"""
txt += """
$1
"""
if do_memory:
txt+="""
if (.not.alloc) then
"""
if do_openmp:
txt += """
!$OMP PARALLEL
!$OMP SINGLE
nthread = omp_get_num_threads()
!$OMP END SINGLE
!$OMP END PARALLEL
"""
else:
txt += """
nthread = 1
"""
txt +="""
print *, 'Allocating irp_stack(',STACKMAX,',0:',nthread,')'
print *, 'Allocating irp_cpu(',STACKMAX,',0:',nthread,')'
print *, 'Allocating stack_index(0:',nthread,')'
endif
"""
txt += """
$2
end subroutine
subroutine irp_leave (irp_where)
use irp_stack_mod
character*(*) :: irp_where
integer :: ithread
double precision :: cpu
"""
if do_openmp:
txt += """
integer, external :: omp_get_thread_num
ithread = omp_get_thread_num()
"""
else:
txt += """
ithread = 0
"""
txt += """
$3
$4
end subroutine
"""
# $1
if do_assert or do_debug:
s = """
if (.not.alloc) then
"""
if do_openmp:
s += """
!$OMP PARALLEL
!$OMP SINGLE
nthread = omp_get_num_threads()
!$OMP END SINGLE
!$OMP END PARALLEL
!$OMP CRITICAL
if (.not.alloc) then
allocate(irp_stack(0:STACKMAX,0:nthread))
allocate(irp_cpu(0:STACKMAX,0:nthread))
allocate(stack_index(0:nthread))
stack_index = 0
alloc = .True.
endif
!$OMP END CRITICAL
endif
stack_index(ithread) = min(stack_index(ithread)+1,STACKMAX)
irp_stack(stack_index(ithread),ithread) = irp_where"""
else:
s += """
nthread = 1
if (.not.alloc) then
allocate(irp_stack(0:STACKMAX,1))
allocate(irp_cpu(0:STACKMAX,1))
allocate(stack_index(2))
stack_index = 0
alloc = .True.
endif
endif
stack_index(1) = min(stack_index(1)+1,STACKMAX)
irp_stack(stack_index(1),1) = irp_where"""
if do_memory:
txt+="""
print *, 'Allocating irp_stack(',STACKMAX,'0:',nthread,')'
print *, 'Allocating irp_cpu(',STACKMAX,'0:',nthread,')'
print *, 'Allocating stack_index(0:',nthread,')'"""
else:
s = ""
txt = txt.replace("$1",s)
# $2
if do_debug:
txt = txt.replace("$2","""
print *, ithread, ':', white(1:stack_index(ithread))//'-> ', trim(irp_where)
call cpu_time(irp_cpu(stack_index(ithread),ithread))""")
else:
txt = txt.replace("$2","")
# $3
if do_debug:
txt = txt.replace("$3","""
call cpu_time(cpu)
print *, ithread, ':', white(1:stack_index(ithread))//'<- ', &
trim(irp_stack(stack_index(ithread),ithread)), &
cpu-irp_cpu(stack_index(ithread),ithread)""")
else:
txt = txt.replace("$3","")
# $4
if do_debug or do_assert:
txt = txt.replace("$4","""
stack_index(ithread) = max(0,stack_index(ithread)-1)""")
else:
txt = txt.replace("$4","")
txt += """
subroutine irp_trace
use irp_stack_mod
integer :: ithread
integer :: i
"""
if do_openmp:
txt += """
!$ integer, external :: omp_get_thread_num
!$ ithread = omp_get_thread_num()
"""
else:
txt += """
ithread = 0
"""
txt += """
if (.not.alloc) return
print *, 'Stack trace: ', ithread
print *, '-------------------------'
do i=1,stack_index(ithread)
print *, trim(irp_stack(i,ithread))
enddo
print *, '-------------------------'
end subroutine
"""
util.lazy_write_file(FILENAME,txt)

View File

@ -35,17 +35,18 @@ except:
from command_line import command_line from command_line import command_line
from irpy_files import Irpy_comm_world from irpy_files import Irpy_comm_world
def main(): def main():
vim.install() vim.install()
if command_line.do_help: if command_line.do_help:
command_line.usage() command_line.usage()
return return
if command_line.do_version: if command_line.do_version:
from version import version from version import version
print version print version
return return
if command_line.do_init: if command_line.do_init:
from build_file import create_generalmakefile from build_file import create_generalmakefile
@ -55,21 +56,98 @@ def main():
comm_world = Irpy_comm_world() comm_world = Irpy_comm_world()
if command_line.do_graph: if command_line.do_graph:
comm_world.t_filename_parsed_text # Initialize entity need. Dirty I know. # Create a dot reprenstion of the dependency graph.
# Merge inside a subgraph the Entity provided together
print 'graph { ' def print_full_diagram(l_entity):
for name,entity in comm_world.d_entity.items():
if entity.needs: l_entity_not_leaf = [e for e in l_entity if e.needs]
print ' {0} -> {1}'.format(name, ' '.join(entity.needs)) print 'digraph Full { '
print '}' for e in l_entity_not_leaf:
print ' %s -> { %s } ' % (e.name, ' '.join(e.needs))
print '}'
def print_subgraph(l_tuple, name, color):
for i, s in enumerate(l_tuple):
print ' subgraph cluster_%s_%s {' % (name, i)
print ' %s ' % ' '.join(s)
print ' color = %s ' % color
print ' }'
comm_world.t_filename_parsed_text # Initialize entity need. Dirty I know.
print_full_diagram(comm_world.d_entity.values())
print 'digraph Compact { '
print ' graph [ordering="out" splines=true overlap=false];'
l_main_usr = set([entity for entity in comm_world.d_entity.values() if entity.is_main])
l_main_head_usr = set([entity for entity in l_main_usr if entity.l_others_name])
l_set_main_head_name = [set(e.l_name) for e in l_main_head_usr]
print_subgraph(l_set_main_head_name, 'usr', color='blue')
from util import l_dummy_entity
l_set_dummy_name = l_dummy_entity(comm_world.d_entity)
print_subgraph(l_set_dummy_name, 'dummy', color='red')
#~=~=~=~=
# Create List Node Uniq
#~=~=~=~=
from util import split_l_set, flatten
l_main_dummy_name, s_exculde_dummy_name = split_l_set(l_set_dummy_name)
l_name_dummy_name_flatten = flatten(l_set_dummy_name)
l_main_head_dummy = set([comm_world.d_entity[name] for name in l_name_dummy_name_flatten])
s_exculde_dummy = set([comm_world.d_entity[name] for name in s_exculde_dummy_name])
l_node_uniq = (l_main_usr | l_main_head_dummy) - s_exculde_dummy
#~=~=~=~=
# Create All edge
#~=~=~=~=
# We need to remove the spurious edge caused by the the dummy multiples providers
d_need = dict()
for e in l_node_uniq:
d_need[e.name] = set(e.needs)
#~=~=~=~=
# Create All edge
#~=~=~=~=
# Draw the eddge
# If a arrow if arriving into Multipliple provider and if it is bold this mean it use all the entity inside it.
from util import uniquify
l_set_multiple = uniquify(l_set_dummy_name + l_set_main_head_name)
l_name_usr = [e.name for e in l_main_head_usr]
for source, l_target in d_need.items():
if source in l_name_usr:
color = 'blue'
elif source in l_name_dummy_name_flatten:
color = 'red'
else:
color = 'black'
for s in l_set_multiple:
if s.issubset(l_target):
print ' %s -> %s [color="%s", penwidth=2]' % (source, sorted(s).pop(), color)
l_target = l_target - s
if l_target:
print ' %s -> { %s } [color="%s"]' % (source, ' '.join(l_target), color)
print ' }'
return return
if command_line.do_preprocess: if command_line.do_preprocess:
for filename, text in comm_world.preprocessed_text: for filename, text in comm_world.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 return
if command_line.do_touch: if command_line.do_touch:
@ -96,10 +174,13 @@ def main():
comm_world.create_buildfile(command_line.do_ninja) comm_world.create_buildfile(command_line.do_ninja)
comm_world.write_modules() comm_world.write_modules()
comm_world.create_touches() comm_world.create_touches()
comm_world.create_man() comm_world.create_man()
if command_line.do_debug or command_line.do_assert:
comm_world.create_stack()
if command_line.do_profile: if command_line.do_profile:
import profile import profile
profile.run(comm_world.d_entity) profile.run(comm_world.d_entity)
@ -107,5 +188,6 @@ def main():
if command_line.do_openmp: if command_line.do_openmp:
comm_world.create_lock() comm_world.create_lock()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -24,249 +24,269 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import sys import sys
import re import re
LENMAX = 70 LENMAX = 70
tabn = 2 tabn = 2
tab = " "*tabn tab = " " * tabn
class Grep(object): class Grep(object):
re_begin_program = re.compile(r"^\s*program\s",flags=re.I) re_begin_program = re.compile(r"^\s*program\s", flags=re.I)
def begin_program(self,string):
return re.match(self.re_begin_program,string) is not None
re_end_program = re.compile(r"\s*(end\s*!?$|end\s*program)",flags=re.I) def begin_program(self, string):
def end_program(self,string): return re.match(self.re_begin_program, string) is not None
return re.match(self.re_end_program,string) is not None
re_begin_subroutine = re.compile(r"^\s*(recursive)?\s*subroutine\s",flags=re.I) re_end_program = re.compile(r"\s*(end\s*!?$|end\s*program)", flags=re.I)
def begin_subroutine(self,string):
return re.match(self.re_begin_subroutine,string) is not None
re_end_subroutine = re.compile(r"\s*(end\s*!?$|end\s*subroutine)",flags=re.I) def end_program(self, string):
def end_subroutine(self,string): return re.match(self.re_end_program, string) is not None
return re.match(self.re_end_subroutine,string) is not None
re_begin_function = re.compile(r"^.*function\s+.*\(",flags=re.I) re_begin_subroutine = re.compile(r"^\s*(recursive)?\s*subroutine\s", flags=re.I)
def begin_function(self,string):
return re.match(self.re_begin_function,string) is not None
re_end_function = re.compile(r"\s*(end\s*!?$|end\s*function)",flags=re.I) def begin_subroutine(self, string):
def end_function(self,string): return re.match(self.re_begin_subroutine, string) is not None
return re.match(self.re_end_function,string) is not None
re_begin_provider = re.compile(r"^\s*&?begin_provider\s",flags=re.I) re_end_subroutine = re.compile(r"\s*(end\s*!?$|end\s*subroutine)", flags=re.I)
def begin_provider(self,string):
return re.match(self.re_begin_provider,string) is not None
re_end_provider = re.compile(r"^\s*end_provider\s*(!.*)?$", flags=re.I) def end_subroutine(self, string):
def end_provider(self,string): return re.match(self.re_end_subroutine, string) is not None
return re.match(self.re_end_provider,string) is not None
re_begin_do = re.compile(r"^\s*do\s+",flags=re.I) re_begin_function = re.compile(r"^.*function\s+.*\(", flags=re.I)
def begin_do(self,string):
return re.match(self.re_begin_do,string) is not None
re_end_do = re.compile(r"^\s*end\s*do\s*(!.*)?$",flags=re.I) def begin_function(self, string):
def end_do(self,string): return re.match(self.re_begin_function, string) is not None
return re.match(self.re_end_do,string) is not None
re_begin_if = re.compile(r"^\s*if(\(|\s+).*(&|then)\s*(!.*)?$",flags=re.I) re_end_function = re.compile(r"\s*(end\s*!?$|end\s*function)", flags=re.I)
def begin_if(self,string):
return re.match(self.re_begin_if,string) is not None
re_else = re.compile(r"^\s*else",flags=re.I) def end_function(self, string):
def xelse(self,string): return re.match(self.re_end_function, string) is not None
return re.match(self.re_else,string) is not None
re_end_if = re.compile(r"^\s*end\s*if\s*(!.*)?$",flags=re.I) re_begin_provider = re.compile(r"^\s*&?begin_provider\s", flags=re.I)
def end_if(self,string):
return re.match(self.re_end_if,string) is not None
re_begin_select = re.compile(r"^\s*select\s*case",flags=re.I) def begin_provider(self, string):
def begin_select(self,string): return re.match(self.re_begin_provider, string) is not None
return re.match(self.re_begin_select,string) is not None
re_case = re.compile(r"^\s*case\s*\(",flags=re.I) re_end_provider = re.compile(r"^\s*end_provider\s*(!.*)?$", flags=re.I)
def case(self,string):
return re.match(self.re_case,string) is not None
re_end_select = re.compile(r"^\s*end\s*select\s*(!.*)?$",flags=re.I) def end_provider(self, string):
def end_select(self,string): return re.match(self.re_end_provider, string) is not None
return re.match(self.re_end_select,string) is not None
re_continuation = re.compile(r"^\s*\S+.*&") re_begin_do = re.compile(r"^\s*do\s+", flags=re.I)
def continuation(self,string):
return re.match(self.re_continuation,string) is not None def begin_do(self, string):
return re.match(self.re_begin_do, string) is not None
re_end_do = re.compile(r"^\s*end\s*do\s*(!.*)?$", flags=re.I)
def end_do(self, string):
return re.match(self.re_end_do, string) is not None
re_begin_if = re.compile(r"^\s*if(\(|\s+).*(&|then)\s*(!.*)?$", flags=re.I)
def begin_if(self, string):
return re.match(self.re_begin_if, string) is not None
re_else = re.compile(r"^\s*else", flags=re.I)
def xelse(self, string):
return re.match(self.re_else, string) is not None
re_end_if = re.compile(r"^\s*end\s*if\s*(!.*)?$", flags=re.I)
def end_if(self, string):
return re.match(self.re_end_if, string) is not None
re_begin_select = re.compile(r"^\s*select\s*case", flags=re.I)
def begin_select(self, string):
return re.match(self.re_begin_select, string) is not None
re_case = re.compile(r"^\s*case\s*\(", flags=re.I)
def case(self, string):
return re.match(self.re_case, string) is not None
re_end_select = re.compile(r"^\s*end\s*select\s*(!.*)?$", flags=re.I)
def end_select(self, string):
return re.match(self.re_end_select, string) is not None
re_continuation = re.compile(r"^\s*\S+.*&")
def continuation(self, string):
return re.match(self.re_continuation, string) is not None
re_declaration = re.compile(r"^.*::.*$")
def declaration(self, string):
return re.match(self.re_declaration, string) is not None
re_declaration = re.compile(r"^.*::.*$")
def declaration(self,string):
return re.match(self.re_declaration,string) is not None
grep = Grep() grep = Grep()
class indent(object): class indent(object):
def __init__(self):
"""Run the program"""
self.run()
def __init__(self): def format_declaration(self, string, n):
"""Run the program""" l, r = string.split('::')
self.run() return l.strip().ljust(n) + ' :: ' + r.strip()
def format_declaration(self,string,n): def format_continuation(self, string, n):
l,r = string.split('::') buffer = string.split('&')
return l.strip().ljust(n) + ' :: '+ r.strip() if len(buffer) == 1:
l = buffer[0]
def format_continuation(self,string,n): return l
buffer = string.split('&')
if len(buffer) == 1:
l = buffer[0]
return l
else:
l, r = buffer
return l.strip().ljust(69-len(n)) + '&'+ r.strip()
def get_filename(self):
"""The file name is the first argument"""
if '_filename' not in self.__dict__:
try:
self._filename = sys.argv[1]
except:
self._filename = None
return self._filename
filename=property(fget=get_filename)
def get_text(self):
"""The text of the file is a list of lines"""
if '_text' not in self.__dict__:
if self.filename is not None:
f = open(self.filename,'r')
self._text = f.read().splitlines()
f.close()
else:
self._text = sys.stdin.read().splitlines()
return self._text
text=property(fget=get_text)
def indentlevel(self,line):
line = line.rstrip()
k=0
if len(line) > 0:
while line[k] == ' ':
k+=1
return k
def run(self):
lines = self.text
indent0 = " "*self.indentlevel(self.text[0])
k = indent0
line = ""
for i in range(len(self.text)):
prevline = line
line = self.text[i].strip()
if grep.continuation(line):
line = self.format_continuation(line,k)
if grep.continuation(prevline):
print k+2*tab+self.format_continuation(line,k+2*tab)
continue
if grep.begin_subroutine(line):
print line
k = indent0+tab
continue
if grep.begin_function(line):
print line
k = indent0+tab
continue
if grep.begin_program(line):
print line
k = indent0+tab
continue
if grep.begin_provider(line):
if line[0] != '&':
k = indent0+tab
if grep.begin_provider(self.text[i+1].strip()):
print " "+line
else:
print line
else: else:
print line l, r = buffer
continue return l.strip().ljust(69 - len(n)) + '&' + r.strip()
if grep.declaration(line): def get_filename(self):
print k+self.format_declaration(line,30) """The file name is the first argument"""
continue if '_filename' not in self.__dict__:
try:
self._filename = sys.argv[1]
except:
self._filename = None
return self._filename
if grep.begin_do(line): filename = property(fget=get_filename)
print k+line
k += tab
continue
if grep.begin_if(line): def get_text(self):
print k+line """The text of the file is a list of lines"""
k += tab if '_text' not in self.__dict__:
continue if self.filename is not None:
f = open(self.filename, 'r')
self._text = f.read().splitlines()
f.close()
else:
self._text = sys.stdin.read().splitlines()
return self._text
if grep.xelse(line): text = property(fget=get_text)
print k[:-tabn]+line
continue
if grep.begin_select(line): def indentlevel(self, line):
print k+line line = line.rstrip()
k += 2*tab k = 0
continue if len(line) > 0:
while line[k] == ' ':
k += 1
return k
if grep.case(line): def run(self):
print k[:-tabn]+line lines = self.text
continue indent0 = " " * self.indentlevel(self.text[0])
if grep.end_do(line):
k = k[:-tabn]
print k+line
continue
if grep.end_if(line):
k = k[:-tabn]
print k+line
continue
if grep.end_select(line):
k = k[:-2*tabn]
print k+line
continue
if grep.end_subroutine(line):
print line
k = indent0 k = indent0
continue line = ""
for i in range(len(self.text)):
prevline = line
line = self.text[i].strip()
if grep.continuation(line):
line = self.format_continuation(line, k)
if grep.end_function(line): if grep.continuation(prevline):
print line print k + 2 * tab + self.format_continuation(line, k + 2 * tab)
k = indent0 continue
continue
if grep.end_provider(line): if grep.begin_subroutine(line):
print line print line
k = indent0 k = indent0 + tab
continue continue
if grep.end_program(line): if grep.begin_function(line):
print line print line
k = indent0 k = indent0 + tab
continue continue
print k+line if grep.begin_program(line):
print line
k = indent0 + tab
continue
if grep.begin_provider(line):
if line[0] != '&':
k = indent0 + tab
if grep.begin_provider(self.text[i + 1].strip()):
print " " + line
else:
print line
else:
print line
continue
if grep.declaration(line):
print k + self.format_declaration(line, 30)
continue
if grep.begin_do(line):
print k + line
k += tab
continue
if grep.begin_if(line):
print k + line
k += tab
continue
if grep.xelse(line):
print k[:-tabn] + line
continue
if grep.begin_select(line):
print k + line
k += 2 * tab
continue
if grep.case(line):
print k[:-tabn] + line
continue
if grep.end_do(line):
k = k[:-tabn]
print k + line
continue
if grep.end_if(line):
k = k[:-tabn]
print k + line
continue
if grep.end_select(line):
k = k[:-2 * tabn]
print k + line
continue
if grep.end_subroutine(line):
print line
k = indent0
continue
if grep.end_function(line):
print line
k = indent0
continue
if grep.end_provider(line):
print line
k = indent0
continue
if grep.end_program(line):
print line
k = indent0
continue
print k + line
def main(): def main():
indent() indent()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -24,7 +24,6 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
irpdir = "IRPF90_temp/" irpdir = "IRPF90_temp/"
mandir = "IRPF90_man/" mandir = "IRPF90_man/"
@ -32,10 +31,8 @@ from zlib import crc32
import os import os
irp_id = abs(crc32(os.getcwd())) irp_id = abs(crc32(os.getcwd()))
try: from lib.manager import irpy
import irpy from util import logger
except:
import lib_irpy as irpy
class Line(object): class Line(object):
@ -51,36 +48,36 @@ class Line(object):
def __repr__(self): def __repr__(self):
return "%20s:%5d : %s (%s)" % (type(self).__name__, self.i, self.text, self.filename) return "%20s:%5d : %s (%s)" % (type(self).__name__, self.i, self.text, self.filename)
class LineWithName(Line): class LineWithName(Line):
@irpy.lazy_property
def subname(self):
buf = self.lower
if not buf.endswith(')'):
buf += "()"
@irpy.lazy_property l_buf = buf.split('(')
def subname(self): l_name = l_buf[0].split()
buf = self.lower
if not buf.endswith(')'):
buf += "()"
l_buf = buf.split('(') if len(l_name) < 2:
l_name = l_buf[0].split() import loger
logger.error("Syntax Error: %s" % line)
sys.exit(1)
return l_name.pop()
if len(l_name) < 2:
import loger
logger.error("Syntax Error: %s" % line)
sys.exit(1)
return l_name.pop()
l_type = [ l_type = [
'Empty_line', 'Simple_line', "Declaration", "Continue", "Begin_provider", 'Empty_line', 'Simple_line', "Declaration", "Continue", "Begin_provider", "Cont_provider",
"Cont_provider", "End_provider", "Begin_doc", "Doc", "End_doc", "End_provider", "Begin_doc", "Doc", "End_doc", "Begin_shell", "End_shell", "Begin_template",
"Begin_shell", "End_shell", "Begin_template", "End_template", "Subst", "End_template", "Subst", "Assert", "Touch", "SoftTouch", "Irp_read", "Irp_write", "Irp_If",
"Assert", "Touch", "SoftTouch", "Irp_read", "Irp_write", "Irp_If", "Irp_Else", "Irp_Endif", "Openmp", "Directive", "Use", "Do", "Enddo", "If", "Elseif", "Else",
"Irp_Else", "Irp_Endif", "Openmp", "Directive", "Use", "Do", "Enddo", "If", "Endif", "Select", "Case", "End_select", "Provide", "NoDep", "Return", "Include", "Implicit",
"Elseif", "Else", "Endif", "Select", "Case", "End_select", "Provide", "NoDep", "Return", "Include", "Free", "End", "Provide_all", "Contains", 'Type', 'End_module', 'Interface', 'End_interface',
"Implicit", "Free", "End", "Provide_all","Contains",'Type','End_module','Interface','End_interface', 'Where', 'Elsewhere', 'Endwhere'
'Where','Elsewhere','Endwhere'] ]
for t in l_type: for t in l_type:
globals()[t] = type(t, (Line, ), {}) globals()[t] = type(t, (Line, ), {})
for t in ['Subroutine', 'Function', 'Program', 'Call','Module']: for t in ['Subroutine', 'Function', 'Program', 'Call', 'Module']:
globals()[t] = type(t, (LineWithName, ), {}) globals()[t] = type(t, (LineWithName, ), {})

View File

@ -24,17 +24,16 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import os import os
import sys import sys
if __name__ == "__main__": if __name__ == "__main__":
from irpf90_t import mandir from irpf90_t import mandir
entity = sys.argv[1].lower() entity = sys.argv[1].lower()
filename = '%s.l'% entity filename = '%s.l' % entity
if filename not in os.listdir(mandir): if filename not in os.listdir(mandir):
print "Error: `%s` does not exist"% entity print "Error: `%s` does not exist" % entity
sys.exit(-1) sys.exit(-1)
os.system("man %s" % os.path.join(mandir,filename)) os.system("man %s" % os.path.join(mandir, filename))

View File

@ -1,10 +1,8 @@
from util import parmap,lazy_write_file from util import parmap, lazy_write_file
from util import flatten, listdir from util import flatten, listdir
from util import logger
try: from lib.manager import irpy
import irpy
except:
import lib_irpy as irpy
import os import os
import irpf90_t import irpf90_t
@ -12,59 +10,56 @@ import sys
from command_line import command_line from command_line import command_line
from util import logger
class Irpy_comm_world(object): class Irpy_comm_world(object):
'''Maestro.''' '''Maestro.'''
def __init__(self,l_dir=None, l_file=None): def __init__(self, l_dir=None, l_file=None):
# (Iter, Iter) -> None # (Iter, Iter) -> None
# Create directories # Create directories
from itertools import ifilterfalse from itertools import ifilterfalse
i_folder = ifilterfalse(os.path.exists, (irpf90_t.irpdir, irpf90_t.mandir)) i_folder = ifilterfalse(os.path.exists, (irpf90_t.irpdir, irpf90_t.mandir))
map(os.mkdir,i_folder) map(os.mkdir, i_folder)
# List file # List file
l_dir =l_dir if l_dir else (command_line.include_dir+['.']) 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))] l_not_dir = [d for d in l_dir if not (os.path.exists(d) and os.path.isdir(d))]
if l_not_dir: if l_not_dir:
logger.error('Try to include no existing directory: [%s]' % ','.join(l_not_dir)) logger.error('Try to include no existing directory: [%s]' % ','.join(l_not_dir))
sys.exit(1) sys.exit(1)
# Create folder in IRPDIR # Create folder in IRPDIR
i_folder = ifilterfalse(os.path.exists, (os.path.join(irpf90_t.irpdir,d) for d in l_dir)) i_folder = ifilterfalse(os.path.exists, (os.path.join(irpf90_t.irpdir, d) for d in l_dir))
map(os.mkdir, i_folder) map(os.mkdir, i_folder)
s_folder_abs = set(os.path.abspath(path) for path in l_dir) 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)) s_file_folder_all = set(flatten(listdir(path, abspath=True) for path in s_folder_abs))
# Take everything! # Take everything!
s_file_folder = filter(lambda f: os.path.isfile(f) and not f.startswith("."), s_file_folder_all) 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 = set(l_file) if l_file else set()
s_file_tot.update(s_file_folder) s_file_tot.update(s_file_folder)
s_file_rel = set(os.path.relpath(f,self.cwd) for f in s_file_tot) s_file_rel = set(os.path.relpath(f, self.cwd) for f in s_file_tot)
# Lazy Copy file # Lazy Copy file
for f in s_file_rel: for f in s_file_rel:
src = os.path.join(self.cwd,f) src = os.path.join(self.cwd, f)
text_ref = open(src, 'rb').read() text_ref = open(src, 'rb').read()
dest = os.path.join(self.cwd,irpf90_t.irpdir, f) dest = os.path.join(self.cwd, irpf90_t.irpdir, f)
lazy_write_file(dest, text_ref) lazy_write_file(dest, text_ref)
if command_line.do_codelet: if command_line.do_codelet:
s_file_tot.update(command_line.codelet[3]) s_file_tot.update(command_line.codelet[3])
# No filter the irpf90 file # No filter the irpf90 file
self.irpf90_files_ordered=sorted(filter(lambda f: f.endswith(".irp.f") ,s_file_rel)) self.irpf90_files_ordered = sorted(filter(lambda f: f.endswith(".irp.f"), s_file_rel))
@irpy.lazy_property @irpy.lazy_property
def cwd(self): def cwd(self):
@ -75,6 +70,7 @@ class Irpy_comm_world(object):
'''Tuple (filename, preprocessed_text)''' '''Tuple (filename, preprocessed_text)'''
from preprocessed_text import Preprocess_text from preprocessed_text import Preprocess_text
def worker_preprocess(filename): def worker_preprocess(filename):
return (filename, Preprocess_text(filename).preprocessed_text) return (filename, Preprocess_text(filename).preprocessed_text)
@ -104,55 +100,62 @@ class Irpy_comm_world(object):
from entity import Entity from entity import Entity
l_begin = [i for i, line in self.d_type_lines[Begin_provider]] 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_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_provider = [self.l_preprocessed_text[begin:end] for begin, end in zip(l_begin, l_end)]
l_ent = [] l_ent = []
for icount, buf in enumerate(l_provider): for icount, buf in enumerate(l_provider):
from functools import partial from functools import partial
Ent_part = partial(Entity,buf,icount,comm_world=self) Ent_part = partial(Entity, buf, icount, comm_world=self)
ent = Ent_part() ent = Ent_part()
l_ent += [ent] + [Ent_part(other) for other in ent.others_entity_name] l_ent += [ent] + [Ent_part(name) for name in ent.l_others_name]
# O(2) but who care # O(2) but who care
l_duplicate = [x for x in l_ent if l_ent.count(x) > 1] l_duplicate = [x for x in l_ent if l_ent.count(x) > 1]
if l_duplicate: if l_duplicate:
from util import logger from util import logger
logger.error('You have duplicate PROVIDER: %s' % ' '.join([e.name for e in l_duplicate])) logger.error('You have duplicate PROVIDER: %s' %
import sys ' '.join([e.name for e in l_duplicate]))
sys.exit(1) import sys
sys.exit(1)
# Python 2.6 Don't allow list comprehesion # Python 2.6 Don't allow list comprehesion
d_ent = dict() d_ent = dict()
for e in l_ent: for e in l_ent:
d_ent[e.name] = e d_ent[e.name] = e
# #
# Second pass # Second pass
#
# Modify parameter of variables # Modify parameter of variables
# Touch Softouch
# Touch Softouch
def find_variable(line): def find_variable(line):
from util import logger
import sys
l_var = line.lower.split()[1:] l_var = line.lower.split()[1:]
if len(l_var) < 1: if len(l_var) < 1:
error.fail(line, "Syntax error") logger.error("Syntax error: %s", line)
import sys
sys.exit(1)
if any(v for v in l_var if v not in d_ent): try:
error.fail(line, "Variable %s unknown" % (v, )) e = next(v for v in l_var if v not in d_ent)
except StopIteration:
pass
else:
logger.error("Entity %s unknown: %s" % (e, line))
import sys
sys.exit(1)
return l_var return l_var
d_modif = dict() d_modif = dict()
from irpf90_t import Touch, SoftTouch, Free from irpf90_t import Touch, SoftTouch, Free
from util import flatten from util import flatten
for cmd, l_type in [('is_self_touched', [Touch, SoftTouch]), for cmd, l_type in [('is_self_touched', [Touch, SoftTouch]), ('is_free', [Free])]:
('is_free', [Free])]:
l_line = flatten( [self.d_type_lines[type_] for type_ in l_type]) l_line = flatten([self.d_type_lines[type_] for type_ in l_type])
l_name = flatten( [find_variable(line) for _, line in l_line]) l_name = flatten([find_variable(line) for _, line in l_line])
d_modif[cmd] = l_name d_modif[cmd] = l_name
# Read and Write # Read and Write
@ -175,7 +178,6 @@ class Irpy_comm_world(object):
Routine is a collection of line between Subroutine / Function Routine is a collection of line between Subroutine / Function
''' '''
# ~#~#~#~#~# # ~#~#~#~#~#
# Create the dict # Create the dict
# ~#~#~#~#~# # ~#~#~#~#~#
@ -187,7 +189,9 @@ class Irpy_comm_world(object):
from routine import Routine from routine import Routine
text = self.l_preprocessed_text 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)] 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 # Now we can create a dict and at it
d_rou = dict() d_rou = dict()
@ -210,11 +214,11 @@ class Irpy_comm_world(object):
from util import uniquify from util import uniquify
for routine in d_rou.values(): for routine in d_rou.values():
for x in routine.calls: for x in routine.calls:
d_called_by[x].add(routine.name) d_called_by[x].add(routine.name)
for routine in d_rou.values(): for routine in d_rou.values():
routine.called_by = sorted(d_called_by[routine.name]) 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] 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) routine.touches_ancestor = set().union(*l_set)
@ -228,18 +232,19 @@ class Irpy_comm_world(object):
import parsed_text import parsed_text
vtuple = [(v, s.same_as, s.regexp) for v, s in d_entity.iteritems()] vtuple = [(v, s.same_as, s.regexp) for v, s in d_entity.iteritems()]
def worker_parsed(filename_text): def worker_parsed(filename_text):
filename, text = filename_text filename, text = filename_text
return parsed_text.get_parsed_text(filename, text, d_entity, d_routine, vtuple) return parsed_text.get_parsed_text(filename, text, d_entity, d_routine, vtuple)
parsed_text_0 = parmap(worker_parsed, self.t_filename_preprocessed_text) parsed_text_0 = parmap(worker_parsed, self.t_filename_preprocessed_text)
from irpf90_t import NoDep, Declaration, Implicit, Use, Cont_provider
from irpf90_t import NoDep,Declaration,Implicit,Use,Cont_provider
def moved_to_top_l(ptext): def moved_to_top_l(ptext):
l = [NoDep, Declaration, Implicit, Use, Cont_provider] l = [NoDep, Declaration, Implicit, Use, Cont_provider]
for _, text in ptext: for _, text in ptext:
parsed_text.move_to_top_list(text, l) parsed_text.move_to_top_list(text, l)
#Touch routine #Touch routine
parsed_text.build_sub_needs(parsed_text_0, d_routine) parsed_text.build_sub_needs(parsed_text_0, d_routine)
@ -247,15 +252,15 @@ class Irpy_comm_world(object):
parsed_text_1 = parsed_text.add_subroutine_needs(parsed_text_0, d_routine) parsed_text_1 = parsed_text.add_subroutine_needs(parsed_text_0, d_routine)
parsed_text_1 = parsed_text.move_variables(parsed_text_1) parsed_text_1 = parsed_text.move_variables(parsed_text_1)
moved_to_top_l(parsed_text_1) moved_to_top_l(parsed_text_1)
parsed_text.check_opt(parsed_text_1) parsed_text.check_opt(parsed_text_1)
parsed_text_1 = parsed_text.perform_loop_substitutions(parsed_text_1) parsed_text_1 = parsed_text.perform_loop_substitutions(parsed_text_1)
#touch entity #touch entity
stuple = [(s, v.regexp) for s, v in d_routine.iteritems() if v.is_function] 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) parsed_text.build_needs(parsed_text_1, d_routine, stuple, d_entity)
return parsed_text_1 return parsed_text_1
@ -264,7 +269,7 @@ class Irpy_comm_world(object):
from module import Fmodule from module import Fmodule
result = dict() result = dict()
for filename, text in self.t_filename_parsed_text: for filename, text in self.t_filename_parsed_text:
result[filename] = Fmodule(text, filename,self.d_entity) result[filename] = Fmodule(text, filename, self.d_entity)
return result return result
@ -276,9 +281,9 @@ class Irpy_comm_world(object):
for m in self.d_module.values(): for m in self.d_module.values():
# Module data # Module data
if m.has_irp_module: if m.has_irp_module:
filename = os.path.join(irpdir, '%s.irp.module.F90' % m.filename) filename = os.path.join(irpdir, '%s.irp.module.F90' % m.filename)
text = '\n'.join(m.header + m.head) text = '\n'.join(m.head)
lazy_write_file(filename, '%s\n' % text) lazy_write_file(filename, '%s\n' % text)
# Subroutines # Subroutines
filename = os.path.join(irpdir, '%s.irp.F90' % m.filename) filename = os.path.join(irpdir, '%s.irp.F90' % m.filename)
@ -286,12 +291,20 @@ class Irpy_comm_world(object):
lazy_write_file(filename, '%s\n' % text) lazy_write_file(filename, '%s\n' % text)
def create_stack(self): def create_stack(self):
import irp_stack from util import lazy_write_file
irp_stack.create() from util import ashes_env
def create_buildfile(self,ninja): str_ = ashes_env.render('irp_stack.f90', {
'do_debug': command_line.do_debug,
'do_openmp': command_line.do_openmp,
'do_memory': command_line.do_memory
})
filename = os.path.join(irpf90_t.irpdir, 'irp_stack.irp.F90')
lazy_write_file(filename, str_)
def create_buildfile(self, ninja):
import build_file import build_file
build_file.run(self.d_module,ninja) build_file.run(self.d_module, ninja)
def create_touches(self): def create_touches(self):
import touches import touches
@ -301,22 +314,10 @@ class Irpy_comm_world(object):
import create_man as c_man import create_man as c_man
c_man.run(self.d_entity, self.d_routine) c_man.run(self.d_entity, self.d_routine)
def create_lock(self): def create_lock(self):
from util import lazy_write_file from util import lazy_write_file
l = sorted(self.d_entity.keys()) from util import ashes_env
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))
str_ = ashes_env.render('irp_lock.f90', {'entity': sorted(self.d_entity)})
filename = os.path.join(irpf90_t.irpdir, 'irp_locks.irp.F90')
lazy_write_file(filename, str_)

0
src/lib/__init__.py Normal file
View File

BIN
src/lib/__init__.pyc Normal file

Binary file not shown.

10
src/lib/manager.py Normal file
View File

@ -0,0 +1,10 @@
try:
import irpy
except:
import static_irpy as irpy
try:
import ashes
except:
import static_ashes as ashes

BIN
src/lib/manager.pyc Normal file

Binary file not shown.

2602
src/lib/static_ashes.py Normal file

File diff suppressed because it is too large Load Diff

BIN
src/lib/static_ashes.pyc Normal file

Binary file not shown.

3
src/lib_irpy.py → src/lib/static_irpy.py Executable file → Normal file
View File

@ -1,4 +1,5 @@
#Handle the execution stack #!/usr/bin/python
from collections import defaultdict from collections import defaultdict
d_path = defaultdict(list) d_path = defaultdict(list)
d_last_caller = defaultdict(lambda: None) d_last_caller = defaultdict(lambda: None)

View File

@ -1,4 +1,4 @@
#!/unr/bin/env python #!/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
@ -30,6 +30,7 @@ import preprocessed_text
from util import * from util import *
from entity import Entity from entity import Entity
def put_info(text, filename): def put_info(text, filename):
lenmax = 80 - len(filename) lenmax = 80 - len(filename)
@ -37,20 +38,19 @@ def put_info(text, filename):
str_ = '{text:{width}} ! {filename}:{i:4}' str_ = '{text:{width}} ! {filename}:{i:4}'
for _, line in text: for _, line in text:
line.text = str_.format(text=line.text,filename=line.filename,i=line.i,width=lenmax) line.text = str_.format(text=line.text, filename=line.filename, i=line.i, width=lenmax)
return text return text
class Fmodule(object): class Fmodule(object):
header = [ "! -*- F90 -*-", header = [
"!", "! -*- F90 -*-", "!", "!-----------------------------------------------!",
"!-----------------------------------------------!", "! This file was generated with the irpf90 tool. !",
"! This file was generated with the irpf90 tool. !", "! !",
"! !", "! DO NOT MODIFY IT BY HAND !",
"! DO NOT MODIFY IT BY HAND !", "!-----------------------------------------------!", ""
"!-----------------------------------------------!", ]
""]
def __init__(self, text, filename, d_variable): def __init__(self, text, filename, d_variable):
self.text = put_info(text, filename) self.text = put_info(text, filename)
@ -74,19 +74,20 @@ class Fmodule(object):
@irpy.lazy_property @irpy.lazy_property
def head(self): def head(self):
'''The module who containt the declaration of the entity''' '''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 self.use or self.dec or self.l_entity:
if body: d_template = {
result = ["module %s" % (self.name)] 'name': self.name,
result += body 'use': list(self.use),
result += ["end module %s" % (self.name)] 'usr_declaration': list(self.dec),
'irp_declaration': [e.d_header for e in self.l_entity],
'coarray': command_line.coarray,
'align': False if command_line.align == 1 else command_line.align
}
return [i for i in ashes_env.render('module.f90', d_template).split('\n') if i]
else: else:
result = [] return []
return result
@irpy.lazy_property @irpy.lazy_property
def has_irp_module(self): def has_irp_module(self):
@ -106,17 +107,17 @@ class Fmodule(object):
result = [] result = []
for var in self.l_entity: for var in self.l_entity:
result += var.provider result += var.provider
result += var.builder if not var.is_protected:
result += var.builder
result += var.allocater
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
return result return result
@irpy.lazy_property @irpy.lazy_property
def residual_text_use_dec(self): def residual_text_use_dec(self):
def remove_providers(text): def remove_providers(text):
result = [] result = []
inside = False inside = False
@ -137,18 +138,18 @@ class Fmodule(object):
skip_interface = False skip_interface = False
for vars, line in text: for vars, line in text:
if type(line) in [Interface, End_interface]: if type(line) in [Interface, End_interface]:
skip_interface = not skip_interface skip_interface = not skip_interface
if skip_interface: if skip_interface:
result.append((vars, line)) result.append((vars, line))
continue continue
if type(line) in [Subroutine, Function, Program]: if type(line) in [Subroutine, Function, Program]:
#Deep copy... #Deep copy...
variable_list = list(vars) variable_list = list(vars)
elif type(line) == End: elif type(line) == End:
result += [([], Use(line.i, x, line.filename)) for x in build_use(variable_list, self.d_all_variable)] 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
@ -160,15 +161,15 @@ class Fmodule(object):
'''Extract the global declaration statement and module use form the declaration of function. ''' '''Extract the global declaration statement and module use form the declaration of function. '''
inside = 0 inside = 0
result,dec,use,module = [],[],[],[] result, dec, use, module = [], [], [], []
for vars, line in text: for vars, line in text:
if isinstance(line, (Subroutine, Function, Program,Interface,Module)): if isinstance(line, (Subroutine, Function, Program, Interface, Module)):
inside += 1 inside += 1
if type(line) == Module: if type(line) == Module:
module.append((vars,line)) module.append((vars, line))
if inside: if inside:
result.append((vars, line)) result.append((vars, line))
@ -178,10 +179,9 @@ class Fmodule(object):
elif type(line) == Declaration: elif type(line) == Declaration:
dec.append((vars, line)) dec.append((vars, line))
if isinstance(line, (End, End_interface, End_module)):
if isinstance(line,(End,End_interface,End_module)):
inside += -1 inside += -1
if inside: if inside:
print 'Something wrong append' print 'Something wrong append'
sys.exit(1) sys.exit(1)
@ -190,9 +190,10 @@ class Fmodule(object):
result = remove_providers(self.text) result = remove_providers(self.text)
result = modify_functions(result) result = modify_functions(result)
from collections import namedtuple from collections import namedtuple
Residual_text_use_dec = namedtuple('Residual_text_use_dec', ['use', 'module', 'dec', 'result']) Residual_text_use_dec = namedtuple('Residual_text_use_dec',
['use', 'module', 'dec', 'result'])
return Residual_text_use_dec(*extract_use_dec_text(result)) return Residual_text_use_dec(*extract_use_dec_text(result))
@ -208,26 +209,26 @@ class Fmodule(object):
@irpy.lazy_property @irpy.lazy_property
def dec(self): def dec(self):
'''The declaration of this module '''The declaration of this module
Note:
Because user can define F90 Type, we need to keep the correct order.
Warning:
If we uniquify that can cause a problem.
```TYPE toto
INTEGER :: n
END TYPE toto
INTEGER :: n
```
Fix:
We need to support TYPE keyword.
Note: '''
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] l = [" %s" % line.text for _, line in self.residual_text_use_dec.dec]
from util import uniquify from util import uniquify
if len(l) != len(uniquify(l)): if len(l) != len(uniquify(l)):
raise NotImplementedError raise NotImplementedError
return l return l
@ -241,23 +242,24 @@ class Fmodule(object):
result += map(lambda x: ([], Simple_line(line.i, x, line.filename)), result += map(lambda x: ([], Simple_line(line.i, x, line.filename)),
build_call_provide(vars, self.d_all_variable)) build_call_provide(vars, self.d_all_variable))
from parsed_text import move_to_top_list, move_interface from parsed_text import move_to_top_list, move_interface
move_to_top_list(result, [Declaration, Implicit, Use]) move_to_top_list(result, [Declaration, Implicit, Use])
move_interface(result) move_interface(result)
return [line.text for _, line in result] return [line.text for _, line in result]
@irpy.lazy_property @irpy.lazy_property
def needed_modules(self): def needed_modules(self):
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 ")) 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 "))
if self.name in l: if self.name in l:
l.remove(self.name) l.remove(self.name)
return l return l
@irpy.lazy_property @irpy.lazy_property
def needed_modules_irp(self): def needed_modules_irp(self):
return [i for i in self.needed_modules if i.endswith("_mod")] return [i for i in self.needed_modules if i.endswith("_mod")]
@ -265,5 +267,3 @@ class Fmodule(object):
@irpy.lazy_property @irpy.lazy_property
def needed_modules_usr(self): def needed_modules_usr(self):
return [i for i in self.needed_modules if not i.endswith("_mod")] return [i for i in self.needed_modules if not i.endswith("_mod")]

View File

@ -34,7 +34,8 @@ regexps_re_string_sub = regexps.re_string.sub
def find_variables_in_line(line, vtuple): def find_variables_in_line(line, vtuple):
line_lower = regexps_re_string_sub('', line.lower) 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)] #return [same_as for v,same_as, regexp in vtuple if v in line_lower and regexp(line_lower)]
return [v for v, same_as, regexp in vtuple if v in line_lower and regexp(line_lower)]
def find_funcs_in_line(line, stuple): def find_funcs_in_line(line, stuple):
@ -56,16 +57,19 @@ def check_touch(variables, line, vars, main_vars):
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_entity_name return [main_var] + x.l_others_name
all_others = uniquify(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):
if x != y: if x != y:
message = "The following entities should be touched:\n" message = "The following entities should be touched:"
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) from util import logger
logger.error("%s (%s)" % (message, line))
import sys
sys.exit(1)
from collections import namedtuple from collections import namedtuple
@ -96,7 +100,8 @@ def get_parsed_text(filename, text, variables, subroutines, vtuple):
varlist.append(v) varlist.append(v)
variable_list = find_variables_in_line(line, vtuple) variable_list = find_variables_in_line(line, vtuple)
variable_list.remove(variables[v].same_as) variable_list.remove(v)
# variable_list.remove(variables[v].same_as)
append(Parsed_text(variable_list, line)) append(Parsed_text(variable_list, line))
@ -109,7 +114,9 @@ def get_parsed_text(filename, text, variables, subroutines, vtuple):
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)) logger.error("Variable %s is unknown (%s)" % (v, line))
import sys
sys.exit(1)
append(Parsed_text(l, Provide(line.i, "", line.filename))) append(Parsed_text(l, Provide(line.i, "", line.filename)))
append(Parsed_text(l, Simple_line(line.i, "!%s" % (line.text), line.filename))) append(Parsed_text(l, Simple_line(line.i, "!%s" % (line.text), line.filename)))
@ -119,6 +126,8 @@ def get_parsed_text(filename, text, variables, subroutines, vtuple):
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))
sys.exit(1)
l = map(lambda x: "-%s" % (x), l) l = map(lambda x: "-%s" % (x), l)
append(Parsed_text(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]:
@ -149,8 +158,9 @@ def get_parsed_text(filename, text, variables, subroutines, vtuple):
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 Parsed_text( return Parsed_text([],
[], Simple_line(line.i, " %s_is_built = .True." % (x, ), line.filename)) 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:
@ -198,6 +208,7 @@ def get_parsed_text(filename, text, variables, subroutines, vtuple):
return (filename, result) return (filename, result)
###################################################################### ######################################################################
def move_to_top_list(text, it): def move_to_top_list(text, it):
# ( List[ List[Entity], Line], Iterator) # ( List[ List[Entity], Line], Iterator)
@ -232,13 +243,13 @@ def move_to_top_list(text, it):
for i, (l_var, line) in enumerate(text): for i, (l_var, line) in enumerate(text):
t = type(line) t = type(line)
if t in [Begin_provider, Module,Program, Subroutine, Function]: if t in [Begin_provider, Module, Program, Subroutine, Function]:
l_begin.append(i) l_begin.append(i)
elif t in [End_provider, End]: elif t in [End_provider, End]:
l_begin.pop() l_begin.pop()
elif l_begin and t in it: elif l_begin and t in it:
d_permutation[t].append( (l_begin[-1], [l_var, line]) ) d_permutation[t].append((l_begin[-1], [l_var, line]))
# Put the sentinel, will be deleted after the insertion # Put the sentinel, will be deleted after the insertion
text[i] = None text[i] = None
@ -265,32 +276,34 @@ def move_to_top_list(text, it):
# Now do the Delete part of the move. Fortunatly we put a sentinel to know the line to delete # 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))): for i in reversed(xrange(len(text))):
if text[i] is None: if text[i] is None:
del text[i] del text[i]
def move_interface(parsed_text,s_type=(Use,Implicit,Declaration,Subroutine,Function,Module)): def move_interface(parsed_text, s_type=(Use, Implicit, Declaration, Subroutine, Function, Module)):
# ( List[ List[Entity], Line], Iterator) # ( List[ List[Entity], Line], Iterator)
'''Move everything containt into 'interface' below the first instance of s_type who preced it '''Move everything containt into 'interface' below the first instance of s_type who preced it
Note: Note:
= This function is impure = This function is impure
''' '''
# Get the born of the interface # Get the born of the interface
i_begin = [ i for i, (_, line) in enumerate(parsed_text) if isinstance(line,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) ] i_end = [i + 1 for i, (_, line) in enumerate(parsed_text) if isinstance(line, End_interface)]
# Get the begin of the insert # Get the begin of the insert
i_insert = [] i_insert = []
for begin in i_begin: 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))) 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 # Do the insert and the delete in one passe
for insert, begin, end in zip(i_insert,i_begin,i_end): for insert, begin, end in zip(i_insert, i_begin, i_end):
parsed_text[insert:insert] = parsed_text[begin:end] parsed_text[insert:insert] = parsed_text[begin:end]
padding = end - begin
parsed_text[begin + padding:end + padding] = []
padding = end-begin
parsed_text[begin+padding:end+padding] = []
###################################################################### ######################################################################
def build_sub_needs(parsed_text, d_subroutine): def build_sub_needs(parsed_text, d_subroutine):
@ -303,10 +316,14 @@ def build_sub_needs(parsed_text, d_subroutine):
l_buffer = [] l_buffer = []
for _, text in parsed_text: for _, text in parsed_text:
l_begin = [ i for i, (_, line) in enumerate(text) if isinstance(line, (Subroutine, Function, Program))] 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_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)] 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: for sub, text in l_buffer:
sub.needs = set(v for vs, _ in text for v in vs) sub.needs = set(v for vs, _ in text for v in vs)
@ -329,11 +346,59 @@ def add_subroutine_needs(parsed_text, subroutines):
###################################################################### ######################################################################
def raise_entity(text):
#(List[ Tuple[List[Entity], Tuple[int,List[Line]] ]]
'''Working progress'''
l_token = []
d_level_var = dict()
d_level_var[0] = []
skip_interface = False
lvl = 0
for i, (e, line) in enumerate(text):
type_ = type(line)
if type_ in [Interface, End_interface]:
skip_interface = not skip_interface
if skip_interface:
continue
if type_ in [Begin_provider, Program, Subroutine, Function, If]:
l_token.append(i)
lvl += 1
d_level_var[lvl] = e[:]
elif type_ in [End_provider, End, Endif]:
i = l_token.pop()
text[i] = (d_level_var[lvl], text[i][1])
lvl += -1
elif type_ in [Else, Elseif]:
i = l_token.pop()
text[i] = (d_level_var[lvl], text[i][1])
assert (type(text[i][1]) == If)
l_token.append(i)
d_level_var[lvl] = e[:]
else:
d_level_var[lvl] += e[:]
text[i] = ([], line)
assert (lvl == 0)
def move_variables(parsed_text): def move_variables(parsed_text):
#(List[ Tuple[List[Entity], Tuple[int,List[Line]] ]] #(List[ Tuple[List[Entity], Tuple[int,List[Line]] ]]
'''Move variables into the top of the declaraiton''' '''Move variables into the top of the declaraiton.
This need to be optimised to handle the fact that we can have multi-provider
'''
def func(filename, text): def func(filename, text):
result = [] result = []
append = result.append append = result.append
@ -346,16 +411,16 @@ def move_variables(parsed_text):
old_elsevars = [] old_elsevars = []
revtext = list(text) revtext = list(text)
revtext.reverse() revtext.reverse()
skip_interface = False skip_interface = False
try: try:
for vars, line in revtext: for vars, line in revtext:
if type(line) in [Interface, End_interface]: if type(line) in [Interface, End_interface]:
skip_interface = not skip_interface skip_interface = not skip_interface
if skip_interface: if skip_interface:
append(([], line)) append(([], line))
continue continue
if type(line) in [End_provider, End]: if type(line) in [End_provider, End]:
varlist = [] varlist = []
@ -406,6 +471,10 @@ def move_variables(parsed_text):
result.reverse() result.reverse()
#print '@@@@@@@@@@@@@'
#for i in text:
# print i
# 2nd pass # 2nd pass
text = result text = result
result = [] result = []
@ -447,7 +516,14 @@ def move_variables(parsed_text):
main_result = [] main_result = []
for filename, text in parsed_text: for filename, text in parsed_text:
#for i in text:
# print i
main_result.append((filename, func(filename, text))) main_result.append((filename, func(filename, text)))
#print '==========='
#for i in main_result[-1][1]:
# print i
return main_result return main_result
@ -459,6 +535,7 @@ def build_needs(parsed_text, subroutines, stuple, variables):
# Needs and to_provide # Needs and to_provide
# ~#~#~#~#~# # ~#~#~#~#~#
# Loop of the main Entity
for filename, text in parsed_text: for filename, text in parsed_text:
l_begin = [i for i, (_, line) in enumerate(text) if isinstance(line, Begin_provider)] l_begin = [i for i, (_, line) in enumerate(text) if isinstance(line, Begin_provider)]
@ -485,6 +562,7 @@ def build_needs(parsed_text, subroutines, stuple, variables):
entity.needs = uniquify(l_needs) entity.needs = uniquify(l_needs)
# Now do the Other entity
for v in variables: for v in variables:
main = variables[v].same_as main = variables[v].same_as
if main != v: if main != v:
@ -492,25 +570,17 @@ def build_needs(parsed_text, subroutines, stuple, variables):
variables[v].to_provide = variables[main].to_provide variables[v].to_provide = variables[main].to_provide
# ~#~#~#~#~# # ~#~#~#~#~#
# Needs and to_provide # Needs_by
# ~#~#~#~#~# # ~#~#~#~#~#
from collections import defaultdict
for v in variables: d_needed_by = defaultdict(list)
variables[v].needed_by = [] for var in variables.values():
for v in variables: for x in var.needs:
main = variables[v].same_as d_needed_by[x].append(var.name)
if main != v:
variables[v].needed_by = variables[main].needed_by
for v in variables: for v in d_needed_by:
var = variables[v] variables[v].needed_by = uniquify(d_needed_by[v])
if var.is_main:
for x in var.needs:
variables[x].needed_by.append(var.same_as)
for v in variables:
var = variables[v]
var.needed_by = uniquify(var.needed_by)
###################################################################### ######################################################################
from command_line import command_line from command_line import command_line
@ -549,4 +619,3 @@ def perform_loop_substitutions(parsed_text):
append((vars, line)) append((vars, line))
main_result.append((filename, result)) main_result.append((filename, result))
return main_result return main_result

View File

@ -37,7 +37,7 @@ re_enddo = re.compile("end +do")
re_endwhere = re.compile("end +where") re_endwhere = re.compile("end +where")
re_endtype = re.compile("end +type.*") re_endtype = re.compile("end +type.*")
re_endmodule = re.compile("end +module",re.I) re_endmodule = re.compile("end +module", re.I)
re_endselect = re.compile("end +select") re_endselect = re.compile("end +select")
re_endinterface = re.compile("end +interface") re_endinterface = re.compile("end +interface")
@ -57,8 +57,11 @@ simple_dict = {
"subst": Subst, "subst": Subst,
"end_doc": End_doc, "end_doc": End_doc,
"begin_provider": Begin_provider, "begin_provider": Begin_provider,
"begin_provider_immutable": Begin_provider,
"&begin_provider": Cont_provider, "&begin_provider": Cont_provider,
"&begin_provider_immutable": Cont_provider,
"end_provider": End_provider, "end_provider": End_provider,
"end_provider_immutable": End_provider,
"assert": Assert, "assert": Assert,
"touch": Touch, "touch": Touch,
"soft_touch": SoftTouch, "soft_touch": SoftTouch,
@ -99,6 +102,7 @@ simple_dict = {
"endwhere": Endwhere, "endwhere": Endwhere,
} }
def get_canonized_text(text_lower): def get_canonized_text(text_lower):
text_canonized = text_lower text_canonized = text_lower
@ -109,7 +113,7 @@ def get_canonized_text(text_lower):
text_canonized = re_endif.sub("endif", text_canonized) text_canonized = re_endif.sub("endif", text_canonized)
text_canonized = re_endselect.sub("endselect", text_canonized) text_canonized = re_endselect.sub("endselect", text_canonized)
text_canonized = re_endinterface.sub("endinterface", text_canonized) text_canonized = re_endinterface.sub("endinterface", text_canonized)
text_canonized = re_endwhere.sub('endwhere',text_canonized) text_canonized = re_endwhere.sub('endwhere', text_canonized)
for c in """()'"[]""": for c in """()'"[]""":
text_canonized = text_canonized.replace(c, " %s " % c) text_canonized = text_canonized.replace(c, " %s " % c)
@ -119,7 +123,7 @@ def get_canonized_text(text_lower):
def get_type(i, filename, line, line_lower, line_lower_canonized, is_doc): def get_type(i, filename, line, line_lower, line_lower_canonized, is_doc):
# ( int,str,str,str,str,bool) -> Irpf90_t # ( int,str,str,str,str,bool) -> Irpf90_t
'''Find the type of a text line''' '''Find the type of a text line'''
line = line.rstrip() line = line.rstrip()
l_word = line_lower_canonized.split() l_word = line_lower_canonized.split()
@ -147,12 +151,10 @@ def get_type(i, filename, line, line_lower, line_lower_canonized, is_doc):
type_ = simple_dict[firstword] type_ = simple_dict[firstword]
return [type_(i, line, filename)], is_doc return [type_(i, line, filename)], is_doc
#label do-loop (outer: do i=1,sze) #label do-loop (outer: do i=1,sze)
reg_do_lab = ur":\s+do\s+" reg_do_lab = ur":\s+do\s+"
if re.search(reg_do_lab,line_lower): if re.search(reg_do_lab, line_lower):
return [Do(i,line,filename)], is_doc return [Do(i, line, filename)], is_doc
lower_line = line_lower.strip()[1:] lower_line = line_lower.strip()[1:]
@ -173,7 +175,7 @@ def get_type(i, filename, line, line_lower, line_lower_canonized, is_doc):
"irpf90 may not work with preprocessor directives. You can use" "irpf90 may not work with preprocessor directives. You can use"
"Irp_if ... Irp_else ... Irp_endif" "Irp_if ... Irp_else ... Irp_endif"
"instead of" "instead of"
"#ifdef ... #else ... #endif"%line) "#ifdef ... #else ... #endif" % line)
return result, is_doc return result, is_doc
if firstword.startswith("case("): if firstword.startswith("case("):
@ -213,9 +215,14 @@ def save_and_execute(irpdir, scriptname, code, interpreter):
# Execute shell # Execute shell
import util import util
try: try:
text = util.check_output('PYTHONPATH=$PYTHONPATH:. %s %s' % (interpreter, irpdir_scriptname), shell=True, bufsize=-1, cwd=os.path.join(irpdir,'..')) text = util.check_output(
'PYTHONPATH=$PYTHONPATH:. %s %s' % (interpreter, irpdir_scriptname),
shell=True,
bufsize=-1,
cwd=os.path.join(irpdir, '..'))
except: except:
util.logger.error("Something wrong append with embeded '%s' script: %s"% (interpreter, irpdir_scriptname)) util.logger.error("Something wrong append with embeded '%s' script: %s" %
(interpreter, irpdir_scriptname))
import sys import sys
sys.exit(1) sys.exit(1)
@ -230,35 +237,35 @@ def execute_shell(text):
# (List[Line]) -> List[Line] # (List[Line]) -> List[Line]
'''Execute the embedded shell scripts''' '''Execute the embedded shell scripts'''
l_begin = [i for i, line in enumerate(text) if isinstance(line, Begin_shell)]
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_end = [i for i,line in enumerate(text) if isinstance(line,End_shell)] l_output = []
l_output= []
# ~=~=~=~ # ~=~=~=~
# E x e c u t e S h e l l # E x e c u t e S h e l l
# ~=~=~=~ # ~=~=~=~
from util import logger from util import logger
import sys import sys
def fail(l, a, b): def fail(l, a, b):
logger.error("%s In Begin_Shell, %s '%s'" % (l,a, b)) logger.error("%s In Begin_Shell, %s '%s'" % (l, a, b))
sys.exit(1) sys.exit(1)
for begin,end in zip(l_begin,l_end): for begin, end in zip(l_begin, l_end):
header = text[begin] header = text[begin]
header_text = header.text header_text = header.text
for bracket in ['[', ']']: for bracket in ['[', ']']:
n = header_text.count(bracket) n = header_text.count(bracket)
assert n <= 1, fail(header_text, "Too many", bracket) assert n <= 1, fail(header_text, "Too many", bracket)
assert n >= 1, fail(header_text, "Missing", bracket) assert n >= 1, fail(header_text, "Missing", bracket)
else: else:
interpreter = header_text[header_text.find('[')+1: header_text.find(']')].strip() interpreter = header_text[header_text.find('[') + 1:header_text.find(']')].strip()
script = ['%s\n' % l.text for l in text[begin+1:end] ] script = ['%s\n' % l.text for l in text[begin + 1:end]]
scriptname="%s_shell_%d" % (header.filename, header.i) scriptname = "%s_shell_%d" % (header.filename, header.i)
l_output.append(save_and_execute(irpdir, scriptname, script,interpreter)) l_output.append(save_and_execute(irpdir, scriptname, script, interpreter))
# ~=~=~=~ # ~=~=~=~
# R e p l a c e # R e p l a c e
@ -268,12 +275,12 @@ def execute_shell(text):
text_new = text[:] text_new = text[:]
# Because we use slicing and we want to include the end line # Because we use slicing and we want to include the end line
l_end_include = [i+1 for i in l_end] l_end_include = [i + 1 for i in l_end]
padding = 0 padding = 0
for begin,end, out in zip(l_begin,l_end_include,l_output): for begin, end, out in zip(l_begin, l_end_include, l_output):
text_new[begin+padding:end+padding] = out text_new[begin + padding:end + padding] = out
padding += len(out) - (end-begin) padding += len(out) - (end - begin)
return text_new return text_new
@ -340,7 +347,11 @@ 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"
result += save_and_execute(irpdir, scriptname="%s_template_%d" % (line.filename, line.i), code=script,interpreter="python") result += save_and_execute(
irpdir,
scriptname="%s_template_%d" % (line.filename, line.i),
code=script,
interpreter="python")
else: else:
subst += line.text + '\n' subst += line.text + '\n'
@ -414,24 +425,23 @@ def remove_comments(text, form):
def remove_after_bang(str_): def remove_after_bang(str_):
# str -> str # str -> str
i_bang = str_.find('!') i_bang = str_.find('!')
if i_bang == -1:
return str_
else:
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: if i_bang == -1:
return str_[:i].strip() return str_
else:
return str_ 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:
@ -444,7 +454,7 @@ def remove_comments(text, form):
if (newline != "" and newline[0] != "!#"): if (newline != "" and newline[0] != "!#"):
text = remove_after_bang(line.text) text = remove_after_bang(line.text)
if text: if text:
line.text = text line.text = text
result.append(line) result.append(line)
return result return result
@ -544,7 +554,7 @@ def irp_simple_statements(text):
def process_return(line): def process_return(line):
assert type(line) == Return assert type(line) == Return
if command_line.do_assert or command_line.do_debug: if command_line.do_debug:
newline = Simple_line(line.i, " call irp_leave(irp_here)", line.filename) newline = Simple_line(line.i, " call irp_leave(irp_here)", line.filename)
result = [newline, line] result = [newline, line]
else: else:
@ -600,7 +610,7 @@ def irp_simple_statements(text):
def process_end(line): def process_end(line):
'''Add irp_leave if necessary''' '''Add irp_leave if necessary'''
if command_line.do_assert or command_line.do_debug: if command_line.do_debug:
i = line.i i = line.i
f = line.filename f = line.filename
result = [Simple_line(i, " call irp_leave(irp_here)", f), line] result = [Simple_line(i, " call irp_leave(irp_here)", f), line]
@ -611,11 +621,15 @@ def irp_simple_statements(text):
def process_begin_provider(line): def process_begin_provider(line):
assert type(line) == Begin_provider assert type(line) == Begin_provider
import string import string
trans = string.maketrans("[]"," ") trans = string.maketrans("[]", " ")
buffer = line.lower.translate(trans).split(',') buffer = line.lower.translate(trans).split(',')
if len(buffer) < 2: if len(buffer) < 2:
error.fail(line, "Error in Begin_provider statement") import sys
print line
print "Error in Begin_provider statement"
sys.exit(1)
varname = buffer[1].strip() varname = buffer[1].strip()
length = len(varname) length = len(varname)
i = line.i i = line.i
@ -624,7 +638,7 @@ def irp_simple_statements(text):
Begin_provider(i, line.text, (f, varname)), Begin_provider(i, line.text, (f, varname)),
Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, varname), f) Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, varname), f)
] ]
if command_line.do_assert or command_line.do_debug: if command_line.do_debug:
result += [Simple_line(i, " call irp_enter(irp_here)", f), ] result += [Simple_line(i, " call irp_enter(irp_here)", f), ]
return result return result
@ -644,10 +658,12 @@ def irp_simple_statements(text):
length = len(subname) length = len(subname)
i = line.i i = line.i
f = line.filename f = line.filename
result = [ line, Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, subname), f)] result = [
line, Declaration(i, " character*(%d) :: irp_here = '%s'" % (length, subname), f)
]
if command_line.do_assert or command_line.do_debug: if command_line.do_debug:
result += [Simple_line(i, " call irp_enter_f(irp_here)", f), ] result += [Simple_line(i, " call irp_enter_routine(irp_here)", f), ]
return result return result
def process_function(line): def process_function(line):
@ -659,27 +675,42 @@ def irp_simple_statements(text):
result = [ result = [
line, 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: if command_line.do_debug:
result += [Simple_line(i, " call irp_enter_f(irp_here)", f), ] result += [Simple_line(i, " call irp_enter_routine(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]
temp = [Program(0, "program irp_program", program_name)] temp = [Program(0, "program irp_program", program_name)]
if command_line.do_Task:
for i in [" call omp_set_nested(.TRUE.)", "!$omp parallel", "!$omp single"]:
temp += [Simple_line(0, i, line.filename)]
if command_line.do_profile: if command_line.do_profile:
temp += [Simple_line(0, "call irp_init_timer()", line.filename)] temp += [Simple_line(0, "call irp_init_timer()", line.filename)]
if command_line.do_openmp: # Need to choose between lazy lock or are big full initialization
temp += [Simple_line(0, " call irp_init_locks_%s()" % (irp_id), line.filename)] # if command_line.do_openmp:
# temp += [Simple_line(0, " call irp_init_locks_%s()" % (irp_id), line.filename)]
if command_line.do_debug or command_line.do_assert:
temp += [Simple_line(0, " CALL irp_stack_init", line.filename)]
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)]
if command_line.do_Task:
for i in ["!$omp taskwait", "!$omp end single", "!$omp end parallel"]:
temp += [Simple_line(0, i, line.filename)]
temp += [End(0, "end program", line.filename)] temp += [End(0, "end program", line.filename)]
result = temp + process_subroutine( result = temp + process_subroutine(
Subroutine(line.i, "subroutine %s" % (program_name, ), line.filename)) Subroutine(line.i, "subroutine %s" % (program_name, ), line.filename))
return result return result
d = { d = {
@ -696,7 +727,6 @@ 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]
@ -740,13 +770,14 @@ def process_old_style_do(text):
DO 1 i=1,10''' DO 1 i=1,10'''
def change_matching_enddo(begin, number): def change_matching_enddo(begin, number):
for i,line in enumerate(text[begin+1:]): for i, line in enumerate(text[begin + 1:]):
if isinstance(line,(Continue,Enddo)) and line.text.split()[0] == number: if isinstance(line, (Continue, Enddo)) and line.text.split()[0] == number:
text[begin+1+i] = Enddo(line.i, " enddo", line.filename) text[begin + 1 + i] = Enddo(line.i, " enddo", line.filename)
return return
from util import logger from util import logger
logger.error(text[begin], "(%s) Old-style do loops should end with 'continue' or 'end do'" % text[begin]) logger.error(text[begin], "(%s) Old-style do loops should end with 'continue' or 'end do'" %
text[begin])
from util import sys from util import sys
sys.exit(1) sys.exit(1)
@ -786,8 +817,8 @@ def change_single_line_ifs(text):
buffer = line.text buffer = line.text
begin = buffer.find('(') begin = buffer.find('(')
if begin == -1: if begin == -1:
logger.error("No '(' in if statemnt: %s" % line) logger.error("No '(' in if statemnt: %s" % line)
sys.exit(1) sys.exit(1)
level = 0 level = 0
instring = False instring = False
@ -812,7 +843,7 @@ def change_single_line_ifs(text):
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, code.lower(),code.lower(), 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)
@ -831,35 +862,40 @@ def check_begin_end(raw_text):
Maybe more of one 'x' statement in defined cause in 'ifdef/else/endif' statement. Maybe more of one 'x' statement in defined cause in 'ifdef/else/endif' statement.
''' '''
d_block = {Enddo: [Do], d_block = {
Endif: [If], Enddo: [Do],
End_provider: [Begin_provider], Endif: [If],
End_doc: [Begin_doc], End_provider: [Begin_provider],
End: [Program, Subroutine, Function], End_doc: [Begin_doc],
End_module: [Module], End: [Program, Subroutine, Function],
End_interface: [Interface]} End_module: [Module],
End_interface: [Interface]
}
from collections import defaultdict from collections import defaultdict
d_type = defaultdict(list) d_type = defaultdict(list)
for line in raw_text: for line in raw_text:
d_type[type(line)].append(line) d_type[type(line)].append(line)
for t_end, l_begin in d_block.iteritems(): for t_end, l_begin in d_block.iteritems():
n_end = len(d_type[t_end]) n_end = len(d_type[t_end])
n_begin = sum(len(d_type[t_begin]) for t_begin in l_begin) n_begin = sum(len(d_type[t_begin]) for t_begin in l_begin)
if n_end != n_begin: if n_end != n_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) logger.error("You have more close statement than open statement (%s) (%s)",
else: line.filename, t_end)
logger.error('You have more end statement than open statenemt for (%s) (%s)' % (line.filename, t_end)) else:
logger.error('You have more end statement than open statenemt for (%s) (%s)' %
for i in zip([l for i in l_begin for l in d_type[i]], d_type[t_end]): (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) logger.debug(i)
sys.exit(1) sys.exit(1)
###################################################################### ######################################################################
def remove_ifdefs(text): def remove_ifdefs(text):
@ -911,13 +947,13 @@ class Preprocess_text(object):
def text(self): def text(self):
with open(self.filename, 'r') as f: with open(self.filename, 'r') as f:
str_ = f.read() str_ = f.read()
#Dirty thing. We will replace 'end program' by 'end subroutine' #Dirty thing. We will replace 'end program' by 'end subroutine'
#because afterward the program will be replaced by a subroutine... #because afterward the program will be replaced by a subroutine...
import re import re
transform = re.compile(re.escape('end program'), re.IGNORECASE) transform = re.compile(re.escape('end program'), re.IGNORECASE)
return transform.sub('end subroutine', str_) return transform.sub('end subroutine', str_)
@irpy.lazy_property_mutable @irpy.lazy_property_mutable
@ -951,7 +987,8 @@ class Preprocess_text(object):
result = [] result = []
is_doc = False is_doc = False
for i, (l, ll, llc) in enumerate(zip(self.lines, self.lines_lower, self.lines_lower_canonized)): 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) line, is_doc = get_type(i + 1, self.filename, l, ll, llc, is_doc)
result += line result += line
return result return result
@ -978,6 +1015,5 @@ class Preprocess_text(object):
return result return result
if __name__ == '__main__': if __name__ == '__main__':
debug() debug()

View File

@ -24,7 +24,6 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
rdtsc = """ rdtsc = """
#ifdef __i386 #ifdef __i386
double irp_rdtsc_(void) { double irp_rdtsc_(void) {
@ -47,14 +46,16 @@ import os
import threading import threading
from irpf90_t import irpdir from irpf90_t import irpdir
def build_rdtsc(): def build_rdtsc():
filename = irpdir+"irp_rdtsc.c" filename = irpdir + "irp_rdtsc.c"
file = open(filename,'w') file = open(filename, 'w')
file.write(rdtsc) file.write(rdtsc)
file.close() file.close()
def build_module(variables): def build_module(variables):
data = """ data = """
module irp_timer module irp_timer
double precision :: irp_profile(3,%(n)d) double precision :: irp_profile(3,%(n)d)
integer :: irp_order(%(n)d) integer :: irp_order(%(n)d)
@ -153,23 +154,23 @@ subroutine irp_print_timer()
print *, 'rdtsc latency :', irp_rdtsc_shift, ' cycles' print *, 'rdtsc latency :', irp_rdtsc_shift, ' cycles'
end end
""" """
label = {} label = {}
for i in variables: for i in variables:
vi = variables[i] vi = variables[i]
label[vi.label] = vi.same_as label[vi.label] = vi.same_as
text = [] text = []
lmax = 0 lmax = 0
for l in label: for l in label:
text.append(" irp_profile_label(%d) = '%s'"%(l,label[l])) text.append(" irp_profile_label(%d) = '%s'" % (l, label[l]))
lmax = max(lmax,l) lmax = max(lmax, l)
text.sort() text.sort()
text = '\n'.join(text) text = '\n'.join(text)
data = data%{'text': text, 'n':lmax} data = data % {'text': text, 'n': lmax}
file = open("IRPF90_temp/irp_profile.irp.F90",'w') file = open("IRPF90_temp/irp_profile.irp.F90", 'w')
file.write(data) file.write(data)
file.close() file.close()
def run(d_entity): def run(d_entity):
build_module(d_entity) build_module(d_entity)
build_rdtsc() build_rdtsc()

View File

@ -24,34 +24,18 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import re import re
re_comment = re.compile(r"^([^'!]*)('[^']*'[^']*)*!") re_comment = re.compile(r"^([^'!]*)('[^']*'[^']*)*!")
re_decl = re.compile( "".join( [ r"^\ *", re_decl = re.compile("".join([
r"(integer[(::)?\* ,]+", r"^\ *", r"(integer[(::)?\* ,]+", r"|double *precision[(::)?\* ,]+", r"|logical[(::)?\* ,]+",
r"|double *precision[(::)?\* ,]+", r"|character[(::)?\* ,]+", r"|real[(::)?\* ,]+", r"|dimension[(::)?\* ,]+",
r"|logical[(::)?\* ,]+", r"|parameter[(::)?\* ,]+", r"|data */", r"|allocatable *(::)?", r"|common */", r"|namelist */",
r"|character[(::)?\* ,]+", r"|save */", r"|complex[(::)?\* ,]+", r"|intrinsic *(::)?", r"|external *(::)?",
r"|real[(::)?\* ,]+", r"|equivalence *(::)?", r"|type", r"|endtype", r")[^=(]"
r"|dimension[(::)?\* ,]+", ]))
r"|parameter[(::)?\* ,]+",
r"|data */",
r"|allocatable *(::)?",
r"|common */",
r"|namelist */",
r"|save */",
r"|complex[(::)?\* ,]+",
r"|intrinsic *(::)?",
r"|external *(::)?",
r"|equivalence *(::)?",
r"|type",
r"|endtype",
r")[^=(]"
] ) )
re_test = re.compile(r"\( *(.*)(\.[a-zA-Z]*\.|[<>]=?|[=/]=)([^=]*)\)") re_test = re.compile(r"\( *(.*)(\.[a-zA-Z]*\.|[<>]=?|[=/]=)([^=]*)\)")
re_string = re.compile(r"'.*?'") re_string = re.compile(r"'.*?'")

View File

@ -24,81 +24,80 @@
# 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 util import logger from util import logger
from lib.manager import irpy
try:
import irpy
except:
import lib_irpy as irpy
class Routine(object): class Routine(object):
''' '''
A collection of list corresponding of a Routine (Subroutine, or function) 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
def __init__(self,text): self.prototype = self.text[0]
assert type(text) == list assert isinstance(self.prototype, (Subroutine, Function))
assert len(text) > 0
self.text = text ############################################################
self.prototype = self.text[0] @irpy.lazy_property_mutable
assert isinstance(self.prototype, (Subroutine, Function)) def called_by(self):
############################################################
@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 raise AttributeError
@irpy.lazy_property ############################################################
def touches(self):
@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)) return list(self.touches_my_self.union(self.touches_ancestor))
############################################################ ############################################################
@irpy.lazy_property @irpy.lazy_property
def regexp(self): def regexp(self):
import re import re
return re.compile(r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I) return re.compile(r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)" % (self.name), re.I)
############################################################ ############################################################
@irpy.lazy_property @irpy.lazy_property
def calls(self): def calls(self):
return set(line.text.split('(',1)[0].split()[1].lower() for line in self.text if isinstance(line,Call)) return set(
line.text.split('(', 1)[0].split()[1].lower() for line in self.text
if isinstance(line, Call))

View File

@ -0,0 +1,50 @@
{?dim}
SUBROUTINE allocate_{name}
{#l_module}
USE {.}
{/l_module}
IMPLICIT NONE
CHARACTER*(9+{@size key=name/}),PARAMETER :: irp_here = 'allocate_{name}'
INTEGER :: irp_err
LOGICAL :: alloc
alloc = ALLOCATED({name})
IF ( alloc .AND.( &
{#l_dim}
( SIZE({name},{rank}) == {value} ) {@sep}.OR.{/sep} &
{/l_dim})) THEN
RETURN
ELSE IF (.NOT.alloc) THEN
GO TO 666
ELSE
{?do_memory} PRINT*, irp_here//': Deallocated {name}' {/do_memory}
DEALLOCATE({name},STAT=irp_err)
IF (irp_err /= 0) THEN
PRINT*, irp_here//': Deallocation failed: {name}'
PRINT*,' size: {dim}'
ENDIF
GO TO 666
ENDIF
666 CONTINUE
{?do_memory} PRINT*, irp_here//': Allocate {name} ({dim})'{/do_memory}
{^do_corray}
ALLOCATE({name} ({dim}), STAT=irp_err)
{:else}
ALLOCATE({name} ({dim}[*]), STAT=irp_err)
{/do_corray}
IF (irp_err /= 0) then
PRINT*, irp_here//': Allocation failed: {name}'
PRINT*,' size: {dim}'
ENDIF
END SUBROUTINE allocate_{name}
{/dim}

View File

@ -0,0 +1,13 @@
SUBROUTINE irp_finalize_{id}
{#use}
USE {.}
{/use}
IMPLICIT NONE
{#entity_array}
IF (ALLOCATED({name})) THEN
{name_root}_is_built = .FALSE.
DEALLOCATE({name})
ENDIF
{/entity_array}
END SUBROUTINE irp_finalize_{id}

View File

@ -0,0 +1,94 @@
# make | ninja
##############
BUILD_SYSTEM= {BUILD_SYSTEM}
#######
IRPF90= irpf90
IRPF90FLAGS= {irpf90_flags}
.EXPORT_ALL_VARIABLES:
LIB = {LIB}
SRC = {SRC}
OBJ = {OBJ}
# Compiler ! Will be overwriten by the ENV one if avalaible.
FC ?= {FC}
FCFLAGS ?= {FCFLAGS}
CC ?= {CC}
CFLAGS ?= {CFLAGS}
CXX ?= {CXX}
CXXFLAGS ?= {CXXFLAGS}
# Dark magic below modify with caution!
# "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\_! _// \\_
#Misc
AR ?= {ar}
RANLIB ?= {ranlib}
# Variable need by IRPF90
BUILD_SYSTEM_stripped=$(strip $(BUILD_SYSTEM))
ifeq ($(BUILD_SYSTEM_stripped),ninja)
BUILD_FILE=IRPF90_temp/build.ninja
IRPF90FLAGS += -j
else ifeq ($(BUILD_SYSTEM_stripped),make)
BUILD_FILE=IRPF90_temp/build.make
BUILD_SYSTEM += -j
else
DUMMY:
$(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)')
endif
# Actual Rule
EXE := $(shell egrep -ri '^\s*program' *.irp.f | cut -d'.' -f1)
ARCH = $(addprefix $(CURDIR)/,IRPF90_temp/irpf90.a)
.PHONY: clean all
all: $(EXE)
define run
$(BUILD_SYSTEM_stripped) -C $(dir $(BUILD_FILE) ) -f $(notdir $(BUILD_FILE) ) $(1)
endef
#We allow for the user to ask for 'relative' path
#But the IRPF90 build system use absolute path.
$(EXE): $(ARCH)
@printf "%b" "\033[0;32m Build $@...\033[m\n"
@$(call run, $(addprefix $(CURDIR)/, $@)) && touch $@
.NOTPARALLEL: $(BUILD_FILE) $(ARCH)
$(ARCH): $(BUILD_FILE)
@printf "%b" "\033[0;32m Creating the archive...\033[m\n"
@$(call run, $@) && touch $@
$(BUILD_FILE): $(shell find . -maxdepth 2 -path ./IRPF90_temp -prune -o -name '*.irp.f' -print)
@printf "%b" "\033[0;32m Running the IRPF90-compiler...\033[m\n"
@$(IRPF90) $(IRPF90FLAGS)
clean:
rm -f -- $(BUILD_FILE) $(EXE)
veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags

71
src/templates/ioer.f90 Normal file
View File

@ -0,0 +1,71 @@
SUBROUTINE writer_{name}(irp_num)
USE {fmodule}
IMPLICIT NONE
CHARACTER*(*), INTENT(IN) :: irp_num
LOGICAL :: irp_is_open = .TRUE.
INTEGER :: irp_iunit = 9
{?do_debug}
CHARACTER*(7+{@size key=name/}),PARAMETER :: irp_here = 'writer_{name}'
{/do_debug}
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
IF (.NOT.{same_as}_is_built) THEN
CALL provide_{same_as}
ENDIF
{#children}
CALL writer_{.}(irp_num)
{/children}
DO WHILE (irp_is_open)
irp_iunit = irp_iunit + 1
INQUIRE(UNIT=irp_iunit, OPENED=irp_is_open)
END DO
{#group_entity}
OPEN(UNIT=irp_iunit,file='irpf90_{name}_'//trim(irp_num),FORM='FORMATTED',STATUS='UNKNOWN',ACTION='WRITE')
WRITE(irp_iunit,*) {name}{dim}
CLOSE(irp_iunit)
{/group_entity}
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
END SUBROUTINE writer_{name}
!TOKEN_SPLIT
SUBROUTINE reader_{name}(irp_num)
USE {fmodule}
IMPLICIT NONE
CHARACTER*(*), INTENT(IN) :: irp_num
LOGICAL :: irp_is_open = .TRUE.
INTEGER :: irp_iunit = 9
{?do_debug}
CHARACTER*(5+{@size key=name/}),PARAMETER :: irp_here = 'read_{name}'
{/do_debug}
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
DO WHILE (irp_is_open)
irp_iunit = irp_iunit + 1
INQUIRE(UNIT=irp_iunit, OPENED=irp_is_open)
END DO
{#group_entity}
OPEN(UNIT=irp_iunit,file='irpf90_{name}_'//trim(irp_num),FORM='FORMATTED',STATUS='OLD',ACTION='READ')
READ(irp_iunit,*) {name}{dim}
CLOSE(irp_iunit)
{/group_entity}
CALL touch_{same_as}
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
END SUBROUTINE reader_{name}

View File

@ -0,0 +1,31 @@
{#entity}
SUBROUTINE irp_lock_{.}(set)
USE omp_lib
IMPLICIT NONE
LOGICAL, INTENT(in) :: set
INTEGER(KIND=omp_lock_kind),SAVE :: {.}_lock
INTEGER, SAVE :: ifirst = 0
{?do_debug}
CHARACTER*(9+{@size key={.}/}),PARAMETER :: irp_here = 'irp_lock_{name}'
{/do_debug}
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
IF (ifirst == 0) then
ifirst = 1
CALL omp_init_lock({.}_lock)
ENDIF
IF (set) THEN
CALL omp_set_lock({.}_lock)
ELSE
CALL omp_unset_lock({.}_lock)
ENDIF
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
END SUBROUTINE irp_lock_{.}
{/entity}

151
src/templates/irp_stack.f90 Normal file
View File

@ -0,0 +1,151 @@
MODULE irp_stack_mod
INTEGER, PARAMETER :: STACKMAX=1000
CHARACTER*(128) ,allocatable :: irp_stack(:,:)
DOUBLE PRECISION ,allocatable :: irp_cpu(:,:)
INTEGER ,allocatable :: stack_index(:)
INTEGER :: nthread
CHARACTER*(128) :: white = ''
END MODULE
SUBROUTINE irp_stack_init
USE irp_stack_mod
IMPLICIT NONE
INTEGER :: ithread
{?do_openmp}
INTEGER, EXTERNAL :: omp_get_thread_num
INTEGER, EXTERNAL :: omp_get_max_threads
{/do_openmp}
INTEGER :: ierr
{^do_openmp}
ithread = 0
{:else}
ithread = omp_get_thread_num()
{/do_openmp}
{^do_openmp} !$OMP CRITICAL {/do_openmp}
IF (.NOT.ALLOCATED(stack_index) ) THEN
{^do_openmp}
nthread = 1
{:else}
nthread = omp_get_max_threads()
{/do_openmp}
{?do_memory}
print *, 'Allocating irp_stack(0:',STACKMAX,',0:',nthread,')'
print *, 'Allocating irp_cpu(0:',STACKMAX,',0:',nthread,')'
print *, 'Allocating stack_index(0:',nthread,')'
{/do_memory}
ALLOCATE ( irp_stack(0:STACKMAX, 0:nthread), &
irp_cpu(0:STACKMAX, 0:nthread), &
stack_index(0:nthread) )
IF (ierr /=0 ) THEN
print*, 'Failed Allocating irp_stack, irp_cpu, stack_index'
ENDIF
stack_index = 0
END IF
END SUBROUTINE
SUBROUTINE irp_enter_routine(irp_where)
USE irp_stack_mod
IMPLICIT NONE
CHARACTER*(*), INTENT(in) :: irp_where
INTEGER :: ithread
REAL :: cpu
{?do_openmp}
INTEGER, EXTERNAL :: omp_get_thread_num
{/do_openmp}
{^do_openmp}
ithread = 0
{:else}
ithread = omp_get_thread_num()
{/do_openmp}
stack_index(ithread) = min(stack_index(ithread)+1,STACKMAX)
irp_stack(stack_index(ithread),ithread) = irp_where
END SUBROUTINE irp_enter_routine
SUBROUTINE irp_enter(irp_where)
USE irp_stack_mod
IMPLICIT NONE
CHARACTER*(*), INTENT(in) :: irp_where
INTEGER :: ithread
{?do_openmp}
INTEGER, EXTERNAL :: omp_get_thread_num
{/do_openmp}
{^do_openmp}
ithread = 0
{:else}
ithread = omp_get_thread_num()
{/do_openmp}
print *, ithread, ':', white(1:stack_index(ithread))//'-> ', trim(irp_where)
CALL cpu_time(irp_cpu(stack_index(ithread),ithread))
END SUBROUTINE irp_enter
SUBROUTINE irp_leave(irp_where)
USE irp_stack_mod
IMPLICIT NONE
CHARACTER*(*), INTENT(in) :: irp_where
INTEGER :: ithread
REAL :: cpu
{?do_openmp}
INTEGER, EXTERNAL :: omp_get_thread_num
{/do_openmp}
{^do_openmp}
ithread = 0
{:else}
ithread = omp_get_thread_num()
{/do_openmp}
CALL cpu_time(cpu)
print *, ithread, ':', white(1:stack_index(ithread))//'<- ', &
trim(irp_stack(stack_index(ithread),ithread)), &
cpu - irp_cpu(stack_index(ithread),ithread)
stack_index(ithread) = max(0,stack_index(ithread)-1)
END SUBROUTINE irp_leave
SUBROUTINE irp_trace
USE irp_stack_mod
IMPLICIT NONE
INTEGER :: ithread
{?do_openmp}
INTEGER, EXTERNAL :: omp_get_thread_num
{/do_openmp}
INTEGER :: i
{^do_openmp}
ithread = 0
{:else}
ithread = omp_get_thread_num()
{/do_openmp}
print *, 'Stack trace: ', ithread
print *, '-------------------------'
DO i=1,stack_index(ithread)
print *, trim(irp_stack(i,ithread))
END DO
print *, '-------------------------'
END SUBROUTINE irp_trace

39
src/templates/module.f90 Normal file
View File

@ -0,0 +1,39 @@
! -*- F90 -*-
!
!-----------------------------------------------!
! This file was generated with the irpf90 tool. !
! !
! DO NOT MODIFY IT BY HAND !
!-----------------------------------------------!
MODULE {name}
{#use}
USE {.}
{/use}
{#usr_declaration}
{.}
{/usr_declaration}
{#irp_declaration}
{^dim}
{type} {?protected}, PROTECTED {/protected} :: {name} {?coarray} [*] {/coarray}
{:else}
{?align} !DIR$ ATTRIBUTES ALIGN: {align} :: {name} {/align}
{type} {?protected}, PROTECTED {/protected} :: {name} {dim} {?coarray} [:] {/coarray}
{/dim}
{?main}
LOGICAL :: {name}_is_built = .FALSE.
{/main}
{/irp_declaration}
CONTAINS
{#irp_declaration}
{protected|s}
{/irp_declaration}
END MODULE {name}

View File

@ -0,0 +1,45 @@
{?inline}!DEC$ ATTRIBUTES FORCEINLINE :: provide_{name}{/inline}
SUBROUTINE provide_{name}
{#l_module}
USE {.}
{/l_module}
IMPLICIT NONE
{?do_debug}
CHARACTER*(8+{@size key=name/}),PARAMETER :: irp_here = 'provide_{name}'
{/do_debug}
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
{?do_openmp}
CALL irp_lock_{name}(.TRUE.)
IF (.NOT.{name}_is_built) THEN
{/do_openmp}
{#l_children_static}
{@first} {?do_task}!$OMP TASKGROUP{/do_task} {/first}
{?do_openmp}!$OMP flush({.}_is_built){/do_openmp}
IF (.NOT.{.}_is_built) THEN
{?do_task}!$OMP TASK{/do_task}
CALL provide_{.}
{?do_task}!$OMP END TASK{/do_task}
ENDIF
{@last} {?do_task}!$OMP END TASKGROUP{/do_task} {/last}
{/l_children_static}
{#l_entity}
{?dim} CALL allocate_{name} {/dim}
{/l_entity}
CALL bld_{name}
{name}_is_built = .TRUE.
{?do_openmp}
ENDIF
CALL irp_lock_{name}(.FALSE.)
{/do_openmp}
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
END SUBROUTINE provide_{name}

26
src/templates/touch.f90 Normal file
View File

@ -0,0 +1,26 @@
{#entity}
SUBROUTINE touch_{name}
{#l_module}
USE {.}
{/l_module}
IMPLICIT NONE
{?do_debug}
CHARACTER*(6+{@size key=name/}),PARAMETER :: irp_here = 'touch_{name}'
{/do_debug}
{?do_debug} CALL irp_enter(irp_here) {/do_debug}
{#l_ancestor}
{.}_is_built = .FALSE.
{/l_ancestor}
{name}_is_built = .TRUE.
{?do_debug} CALL irp_leave(irp_here) {/do_debug}
END SUBROUTINE touch_{name}
{/entity}

View File

@ -24,42 +24,40 @@
# 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 from irpf90_t import irp_id, irpdir
import os import os
from util import lazy_write_file from command_line import command_line
def create(modules,variables):
# (Dict[str,Module]. Dict[str, Variable]) -> None
'''Create the fortran90 finalize subroutine and the touched one'''
def create(modules, variables):
finalize = "subroutine irp_finalize_%s\n"%(irp_id) # (Dict[str,Module]. Dict[str, Variable]) -> None
for m in filter(lambda x: not modules[x].is_main and modules[x].has_irp_module, modules): '''Create the fortran90 finalize subroutine and the touched one'''
finalize += " use %s\n"%(modules[m].name)
main_modules_name =[ m.name for m in modules.values() if m.is_main] main_modules_name = [m.name for m in modules.values() if m.is_main]
out = []
for v,var in variables.iteritems():
if var.fmodule not in main_modules_name: d_template_finalize = {
#if var.is_self_touched: 'id': irp_id,
out += var.toucher 'use': [m.name for m in modules.values() if not m.is_main and m.has_irp_module],
if var.dim: 'entity_array': [{
finalize += " if (allocated(%s)) then\n"%v 'name': e.name,
finalize += " %s_is_built = .False.\n"%var.same_as 'name_root': e.same_as
finalize += " deallocate(%s)\n"%v } for e in variables.values() if e.fmodule not in main_modules_name and e.dim]
finalize += " endif\n" }
finalize += "end\n" d_template_touch = {
'do_debug': command_line.do_debug,
'entity': [
e.d_touche_template for e in variables.values()
if e.fmodule not in main_modules_name and e.d_touche_template
]
}
import util
str_out = util.ashes_env.render('touch.f90', d_template_touch) + util.ashes_env.render(
'finalize.f90', d_template_finalize)
if out: filename = os.path.join(irpdir, 'irp_touches.irp.F90')
out = map(lambda x: "%s\n"%(x),out) util.lazy_write_file(filename, '%s\n' % util.remove_empy_lines(str_out))
out += finalize
filename=os.path.join(irpdir,'irp_touches.irp.F90')
lazy_write_file(filename,''.join(out))
if __name__ == '__main__': if __name__ == '__main__':
create() create()

View File

@ -24,7 +24,6 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
# ~#~#~#~#~# # ~#~#~#~#~#
# L o g e r # L o g e r
# ~#~#~#~#~# # ~#~#~#~#~#
@ -42,19 +41,33 @@ logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('Irpf90') logger = logging.getLogger('Irpf90')
logger.setLevel(30) logger.setLevel(30)
# ~#~#~#~#~#
# A S H E S _ T E M P L A T E S
# ~#~#~#~#~#
from lib.manager import ashes
import os
ashes_env = ashes.AshesEnv([os.path.join(os.path.dirname(__file__), 'templates')])
def remove_empy_lines(text):
return os.linesep.join([s for s in text.splitlines() if s.strip()])
# ~#~#~#~#~# # ~#~#~#~#~#
# / / _ R E L A T E D # / / _ R E L A T E D
# ~#~#~#~#~# # ~#~#~#~#~#
def chunkify(l,n_chunk):
def chunkify(l, n_chunk):
# (List[any], int) -> List [ List[any] ] # (List[any], int) -> List [ List[any] ]
'''Split the list on n_chunk''' '''Split the list on n_chunk'''
len_ = len(l) len_ = len(l)
n = max(1, len_ / n_chunk ) n = max(1, len_ / n_chunk)
return [ l[i:i + n] for i in xrange(0, len_, n) ] return [l[i:i + n] for i in xrange(0, len_, n)]
import multiprocessing import multiprocessing
def parmap(f, it, parallel=False): def parmap(f, it, parallel=False):
# (Callable, Iterable, bool) -> List # (Callable, Iterable, bool) -> List
'''Parallel version of the std map function '''Parallel version of the std map function
@ -70,7 +83,7 @@ def parmap(f, it, parallel=False):
''' '''
if not parallel: if not parallel:
return map(f, it) return map(f, it)
nproc = multiprocessing.cpu_count() nproc = multiprocessing.cpu_count()
@ -98,12 +111,12 @@ def parmap(f, it, parallel=False):
# In this implementation, we minimizise the communication # In this implementation, we minimizise the communication
# (aka 1 job by processor) # (aka 1 job by processor)
it_chunk = chunkify(l=it,n_chunk=nproc) it_chunk = chunkify(l=it, n_chunk=nproc)
def F(chunk): def F(chunk):
# (List[any]) -> (List[any]) # (List[any]) -> (List[any])
'''Same as 'f' but for a chunck''' '''Same as 'f' but for a chunck'''
return map(f,chunk) return map(f, chunk)
q_in = multiprocessing.JoinableQueue() q_in = multiprocessing.JoinableQueue()
q_out = multiprocessing.Queue() q_out = multiprocessing.Queue()
@ -112,8 +125,8 @@ def parmap(f, it, parallel=False):
stop_condition = None stop_condition = None
def worker(): def worker():
# () -> None # () -> None
'''Read a task from q_in, excute it, and store it in q_out '''Read a task from q_in, excute it, and store it in q_out
Note: Note:
- We use 'F' and not 'f'. - We use 'F' and not 'f'.
@ -121,19 +134,19 @@ def parmap(f, it, parallel=False):
- We get, and put an idx to allow the possibility of ordering afterward - We get, and put an idx to allow the possibility of ordering afterward
- We store any exeception, to raise her afterward - We store any exeception, to raise her afterward
''' '''
for i, x in iter(q_in.get, stop_condition): for i, x in iter(q_in.get, stop_condition):
try: try:
result = F(x) result = F(x)
except BaseException as e: except BaseException as e:
t = e t = e
else: else:
t = (i, result) t = (i, result)
q_out.put(t) q_out.put(t)
q_in.task_done() q_in.task_done()
q_in.task_done() q_in.task_done()
# Process' creation # Process' creation
l_proc = [multiprocessing.Process(target=worker) for _ in range(nproc)] l_proc = [multiprocessing.Process(target=worker) for _ in range(nproc)]
@ -152,15 +165,15 @@ def parmap(f, it, parallel=False):
q_in.join() q_in.join()
# Get all the chunk and join the process # Get all the chunk and join the process
l_res = [q_out.get() for _ in range(len(it_chunk))] l_res = [q_out.get() for _ in range(len(it_chunk))]
for p in l_proc: for p in l_proc:
p.join() p.join()
# Check if error have occured # Check if error have occured
try: try:
from itertools import ifilter from itertools import ifilter
e = next(ifilter(lambda t: isinstance(t,BaseException), l_res)) e = next(ifilter(lambda t: isinstance(t, BaseException), l_res))
except StopIteration: except StopIteration:
# Now we need first to order the result, and secondly to flatte it # 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] return [item for _, chunk in sorted(l_res) for item in chunk]
@ -172,6 +185,8 @@ def parmap(f, it, parallel=False):
# ~#~#~#~#~# # ~#~#~#~#~#
import hashlib import hashlib
import os import os
def cached_file(filename, text): def cached_file(filename, text):
# (str,str) -> bool # (str,str) -> bool
'''Check if file locatte at filename containt the same data as text '''Check if file locatte at filename containt the same data as text
@ -183,7 +198,7 @@ def cached_file(filename, text):
def digest(data): def digest(data):
# (str) -> str # (str) -> str
'''compute an uniq data id''' '''compute an uniq data id'''
return hashlib.md5(data).hexdigest() return hashlib.md5(data).hexdigest()
try: try:
text_ref = open(filename, 'rb').read() text_ref = open(filename, 'rb').read()
@ -193,7 +208,7 @@ def cached_file(filename, text):
return digest(text_ref) == digest(text) return digest(text_ref) == digest(text)
def lazy_write_file(filename, text, conservative=False,touch=False): def lazy_write_file(filename, text, conservative=False, touch=False):
# (str, str, bool) -> None # (str, str, bool) -> None
'''Write data lazily in filename location. '''Write data lazily in filename location.
@ -205,7 +220,8 @@ def lazy_write_file(filename, text, conservative=False,touch=False):
with open(filename, 'w') as f: with open(filename, 'w') as f:
f.write(text) f.write(text)
elif touch: elif touch:
os.utime(filename,None) os.utime(filename, None)
def listdir(directory, abspath=False): def listdir(directory, abspath=False):
#(str, bool) -> List[str] #(str, bool) -> List[str]
@ -217,6 +233,7 @@ def listdir(directory, abspath=False):
else: else:
return [os.path.abspath(os.path.join(directory, f)) for f in l_filename] return [os.path.abspath(os.path.join(directory, f)) for f in l_filename]
def check_output(*popenargs, **kwargs): def check_output(*popenargs, **kwargs):
"""Run command with arguments and return its output as a byte string. """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. Backported from Python 2.7 as it's implemented as pure python on stdlib.
@ -241,22 +258,31 @@ def check_output(*popenargs, **kwargs):
# ~#~#~#~#~# # ~#~#~#~#~#
def uniquify(l,sort=False): def uniquify(l, sort=False):
# (Iter, bool) -> List[Any] # (Iter, bool) -> List[Any]
'''Uniquify a immutable iterable. Don't preserve the order''' '''Uniquify a immutable iterable. Don't preserve the order. Or maybe.'''
r = list(set(l))
#Be carefull that element in Iter can be unshable.
try:
r = list(set(l))
except TypeError:
used = list()
r = [x for x in l if x not in used and (used.append(x) or True)]
if not sort: if not sort:
return r return r
else: else:
return sorted(r) return sorted(r)
def OrderedUniqueList(l): def OrderedUniqueList(l):
# (Iter, bool) -> List[Any] # (Iter, bool) -> List[Any]
'''Uniquify a immutable iterable. Don't preserve the order''' '''Uniquify a immutable iterable. Don't preserve the order'''
return sorted(set(l)) return sorted(set(l))
def flatten(l_2d): def flatten(l_2d):
# (List [ List[Any] ]) -> List # (List [ Iter[Any] ]) -> List
'''Construct a copy of the 2d list collapsed into one dimension. '''Construct a copy of the 2d list collapsed into one dimension.
Note: Note:
@ -269,6 +295,28 @@ def flatten(l_2d):
# ~#~#~#~#~# # ~#~#~#~#~#
# I R P _ R E L A T E D # I R P _ R E L A T E D
# ~#~#~#~#~# # ~#~#~#~#~#
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_dim(l_dim, colons=False): def build_dim(l_dim, colons=False):
# (List[str],bool) -> str # (List[str],bool) -> str
'''Contruct a valid fortran90 array dimension code from a list dimension '''Contruct a valid fortran90 array dimension code from a list dimension
@ -286,20 +334,71 @@ def build_dim(l_dim, colons=False):
return "(%s)" % (",".join(l_dim_colons)) return "(%s)" % (",".join(l_dim_colons))
def build_use(l_ent, d_ent): def mangled(l_ent, d_ent):
# (List, Dict[str,Entity]) -> list
'''Create a uniq list of providier (merge the multione) '''
return OrderedUniqueList(d_ent[name].same_as for name in l_ent)
def build_use(l_ent, d_ent, use=True):
# (List, Dict[str,Entity]) -> list # (List, Dict[str,Entity]) -> list
'''Contruct the fortran90 'use' statement for the list of entity''' '''Contruct the fortran90 'use' statement for the list of entity'''
return OrderedUniqueList(" use %s" % d_ent[x].fmodule for x in l_ent)
l_name = OrderedUniqueList(d_ent[x].fmodule for x in l_ent)
if not use:
return l_name
else:
return [" use %s" % n for n in l_name]
def build_call_provide(l_ent, d_ent): def build_call_provide(l_ent, d_ent):
# (List, Dict[str,Entity]) -> list # (List, Dict[str,Entity]) -> list
'''Construct the fortran 90 call the provider needed by the list of entity''' '''Construct the fortran 90 call the provider needed by the list of entity'''
def fun(x):
return [ " if (.not.%s_is_built) then" % x,
" call provide_%s" % x,
" endif"]
# Get the corect name (in the case of multiple provider line) # Get the corect name (in the case of multiple provider line)
l_same_as = OrderedUniqueList(d_ent[x].same_as for x in l_ent) l_same_as = mangled(l_ent, d_ent)
return flatten(map(fun, l_same_as))
def bld_f90(x):
return [" if (.not.%s_is_built) then" % x, " call provide_%s" % x, " endif"]
return flatten(map(bld_f90, l_same_as))
def che_merge(sets):
#(List[Set] -> List[Set]
"""Merge a list of set is they are not disjoint.
Note:
This will destry sets
"""
results = []
upd, isd, pop = set.update, set.isdisjoint, sets.pop
while sets:
if not [
upd(sets[0], pop(i)) for i in range(len(sets) - 1, 0, -1)
if not isd(sets[0], sets[i])
]:
results.append(pop(0))
return results
def l_dummy_entity(d_entity):
# Dict[str:Entity] -> List[set]
from itertools import combinations
l_candidate_botom = [(i, j) for i, j in combinations(d_entity.keys(), 2)
if d_entity[i].needs == d_entity[j].needs]
l_dummy = [
set([i, j]) for i, j in l_candidate_botom if d_entity[i].needed_by == d_entity[j].needed_by
]
return che_merge(l_dummy)
def split_l_set(l_set_org):
#(List[set] -> (List, Set)
'''Split the list of set into a list of Head and and the concetenad of all the tail
Note: Head and Tail a not defined in set. Head in one element of the set, and tail the rest.
'''
l_set = [set(s) for s in l_set_org]
l_main = [s.pop() for s in l_set]
return l_main, set(flatten(l_set))

View File

@ -24,25 +24,26 @@
# 31062 Toulouse Cedex 4 # 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr # scemama@irsamc.ups-tlse.fr
import os import os
def install(): def install():
VIM = os.environ["HOME"]+"/.vim" VIM = os.environ["HOME"] + "/.vim"
try: try:
if os.access(VIM+"/syntax/irpf90.vim",os.F_OK): if os.access(VIM + "/syntax/irpf90.vim", os.F_OK):
return return
if not os.access(VIM,os.F_OK): if not os.access(VIM, os.F_OK):
os.mkdir(VIM) os.mkdir(VIM)
file = open(VIM+"/filetype.vim","a") file = open(VIM + "/filetype.vim", "a")
file.write("au BufRead,BufNewFile *.irp.f setfiletype irpf90") file.write("au BufRead,BufNewFile *.irp.f setfiletype irpf90")
file.close() file.close()
if not os.access(VIM+"/syntax",os.F_OK): if not os.access(VIM + "/syntax", os.F_OK):
os.mkdir(VIM+"/syntax") os.mkdir(VIM + "/syntax")
wd = os.path.abspath(os.path.dirname(__file__)) wd = os.path.abspath(os.path.dirname(__file__))
os.symlink(wd+"/irpf90.vim",VIM+"/syntax/irpf90.vim") os.symlink(wd + "/irpf90.vim", VIM + "/syntax/irpf90.vim")
except: except:
pass pass
if __name__ == "__main__": if __name__ == "__main__":
install() install()