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

Merge pull request #18 from TApplencourt/master

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

View File

@ -1,13 +1,69 @@
IRPF90 = python ../src/irpf90.py -I input -a -d
FC = ifort
FCFLAGS= -O2
NINJA =
IRPF90= irpf90
IRPF90FLAGS= -I ./ -I input/
BUILD_SYSTEM= make
SRC=
OBJ=
LIB=
.EXPORT_ALL_VARIABLES:
include irpf90.make
AR = ar
CC = gcc
CFLAGS = -O2
CXX = g++
CXXFLAGS = -O2
FC = gfortran
FCFLAGS = -O2
LIB =
RANLIB = ranlib
irpf90.make: $(wildcard *.irp.f)
$(IRPF90)
OBJ =
SRC =
# 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\_! _//^---^\\_
ifeq ($(BUILD_SYSTEM),ninja)
BUILD_FILE=IRPF90_temp/build.ninja
IRPF90FLAGS += -j
else ifeq ($(BUILD_SYSTEM),make)
BUILD_FILE=IRPF90_temp/build.make
BUILD_SYSTEM += -j
else
DUMMY:
$(error 'Wrong BUILD_SYSTEM: $(BUILD_SYSTEM)')
endif
define run_and_touch
$(BUILD_SYSTEM) -C $(dir $(1) ) -f $(notdir $(1) ) $(addprefix $(CURDIR)/, $(2)) && touch $(2)
endef
EXE := $(shell egrep -r '^\s*program' *.irp.f | awk '{print $$2}')
.PHONY: all
all: $(BUILD_FILE)
$(call run_and_touch, $<, $(EXE))
.NOTPARALLEL: $(EXE)
$(EXE): $(BUILD_FILE)
$(call run_and_touch, $<, $(EXE))
$(BUILD_FILE): $(shell find . -maxdepth 2 -path ./IRPF90_temp -prune -o -name '*.irp.f' -print)
$(IRPF90) $(IRPF90FLAGS)
clean:
rm -f -- $(BUILD_FILE) $(EXE) $(shell find IRPF90_temp -type f \( -name "*.o" -o -name "*.mod" -name "*.a" \) -delete;)
veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90_entities dist tags

View File

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

View File

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

3
src/.style.yapf Normal file
View File

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

537
src/build_file.py Normal file
View File

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

View File

@ -1,73 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from irpf90_t import *
from util import *
from variables import variables
from modules import modules
CHECKPOINT_UNIT_NUMBER=63
FILENAME=irpdir+'irp_checkpoint.irp.F90'
def create():
out_write = [ "subroutine irp_checkpoint_write" ]
l = variables.keys()
l.sort
main_modules = filter(lambda x: modules[x].is_main, modules)
for m in filter(lambda x: not modules[x].is_main, modules):
out_write += [ " use %s"%(modules[m].name) ]
out_write += [ " implicit none" ]
out_write += [ " integer, parameter :: iunit = %d"%(CHECKPOINT_UNIT_NUMBER) ]
out_write += [ " open(unit=%d,file='irp_checkpoint.dat',status='UNKNOWN',action='WRITE')"%(CHECKPOINT_UNIT_NUMBER) ]
for v in l:
var = variables[v]
if var.is_main:
out_write += [ " if (%s_is_built) then"%(v) ]
for w in [v]+var.others:
d = variables[w].dim
if d == []:
out_write += [ " write(iunit,*) '%s', 0"%(w) ]
else:
out_write += [ " write(iunit, *) '%s', %d"%(w, len(d)),
" write(iunit, *) %s"%(",".join(
[ "size(%s,%d)"%(w,i+1) for i in range(len(d)) ] ))
]
out_write += [ " write(iunit,*) %s"%(w) ]
out_write += [ " endif" ]
out_write += [ " close(%d)"%(CHECKPOINT_UNIT_NUMBER) ]
out_write += [ "end" ]
out = '\n'.join(out_write)
if not same_file(FILENAME,out):
file = open(FILENAME,'w')
file.writelines(out)
file.close()
if __name__ == '__main__':
create()

View File

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

View File

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

View File

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

View File

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

726
src/entity.py Normal file
View File

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

View File

@ -1,66 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import sys
from irpf90_t import *
from command_line import command_line
do_warnings = command_line.do_warnings
######################################################################
def fail(line,message):
print """
Error:
-----
"""
print message, '\n'
if line is not None:
assert isinstance(line,Line)
print "file %s ; line %d :\n %s"%(line.filename,line.i,line.text)
sys.exit(1)
######################################################################
def warn(line,message):
if not command_line.do_warnings:
return
if line is not None:
assert isinstance(line,Line)
print """
Warning:
-------
"""
print message, '\n'
print "file %s, line %d:\n %s"%(line.filename,line.i,line.text)
else:
print "Warning: %s"%(message)
######################################################################
if __name__ == '__main__':
line = Empty_line(3,"empty", "testfile")
fail(line, "Message")

View File

@ -1,89 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import os
import util
import makefile
import irpf90_t
from command_line import command_line
initialized = False
def init():
global initialized
if initialized:
return
# Create directories
for dir in [ irpf90_t.irpdir, irpf90_t.mandir ]:
try:
wd = os.getcwd()
os.chdir(dir)
os.chdir(wd)
except OSError:
os.mkdir(dir)
for dir in command_line.include_dir:
dir = irpf90_t.irpdir+dir
try:
wd = os.getcwd()
os.chdir(dir)
os.chdir(wd)
except OSError:
os.mkdir(dir)
# Create makefile
makefile.create()
# Copy current files in the irpdir
for dir in ['./']+command_line.include_dir:
try:
os.stat(dir)
except:
print dir,'not in dir'
continue
for filename in os.listdir(dir):
filename = dir+filename
if not filename.startswith(".") and not os.path.isdir(filename):
try:
file = open(filename,"r")
except IOError:
if command_line.do_warnings:
print "Warning : Unable to read file %s."%(filename)
else:
buffer = file.read()
file.close()
if not util.same_file(irpf90_t.irpdir+filename,buffer):
file = open(irpf90_t.irpdir+filename,"w")
file.write(buffer)
file.close()
initialized = True

View File

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

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
#cscs /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
@ -25,95 +24,85 @@
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import vim
import os,sys
import os, sys
try:
wd = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0,(wd+"/../src/"))
wd = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, (wd + "/../src/"))
except:
pass
sys.setcheckinterval(1000)
pass
from command_line import command_line
from irpy_files import Irpy_comm_world
def main():
vim.install()
vim.install()
if command_line.do_help:
command_line.usage()
if command_line.do_help:
command_line.usage()
return
if command_line.do_version:
from version import version
print version
return
if command_line.do_version:
from version import version
print version
if command_line.do_init:
from build_file import create_generalmakefile
create_generalmakefile(command_line.do_ninja)
return
from init import init
if command_line.do_init:
init()
comm_world = Irpy_comm_world()
if command_line.do_preprocess:
init()
from preprocessed_text import preprocessed_text
for filename,text in preprocessed_text:
if filename in command_line.preprocessed:
for line in text:
print line.text
if command_line.do_graph:
comm_world.t_filename_parsed_text # Initialize entity need. Dirty I know.
print 'graph { '
for name,entity in comm_world.d_entity.items():
if entity.needs:
print ' {0} -> {1}'.format(name, ' '.join(entity.needs))
print '}'
return
if command_line.do_touch:
from variables import variables
for var in command_line.touched:
if var not in variables:
print "%s is not an IRP entity"%(var,)
else:
print "Touching %s invalidates the following entities:"%(var,)
parents = variables[var].parents
parents.sort()
for x in parents:
print "- %s"%(x,)
if command_line.do_preprocess:
for filename, text in comm_world.preprocessed_text:
if filename in command_line.preprocessed:
for line in text:
print line.text
return
if command_line.do_codelet:
import profile
profile.build_rdtsc()
import codelet
codelet.run()
if command_line.do_touch:
for var in command_line.touched:
if var not in comm_world.d_entity:
print "%s is not an IRP entity" % var
else:
print "Touching %s invalidates the following entities:" % var
for x in sorted(d_entity[var].parents):
print "- %s" % (x, )
return
if not command_line.do_run:
return
if command_line.do_codelet:
import profile
profile.build_rdtsc()
import codelet
codelet.run()
init()
if not command_line.do_run:
return
import irp_stack
irp_stack.create()
comm_world.create_buildfile(command_line.do_ninja)
comm_world.write_modules()
comm_world.create_touches()
comm_world.create_man()
import makefile
makefile.create()
if command_line.do_profile:
import profile
profile.run(comm_world.d_entity)
from modules import modules, write_module
for m in modules.keys():
write_module(modules[m])
makefile.run()
import touches
touches.create()
# import checkpoint
# checkpoint.create()
import create_man
create_man.run()
if command_line.do_profile:
import profile
profile.run()
if command_line.do_openmp:
import locks
locks.create()
if command_line.do_openmp:
comm_world.create_lock()
if __name__ == '__main__':
main()
main()

View File

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

View File

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

322
src/irpy_files.py Normal file
View File

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

160
src/lib_irpy.py Executable file
View File

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

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from command_line import command_line
from irpf90_t import *
from util import *
from variables import variables
FILENAME=irpdir+'irp_locks.irp.F90'
def create():
out = []
l = variables.keys()
l.sort
for v in l:
var = variables[v]
out += var.locker
out += [
"subroutine irp_init_locks_%s()"%(irp_id),
" implicit none" ]
for v in l:
out += [ " call irp_lock_%s(.True.)"%v ]
out += [ " call irp_lock_%s(.False.)"%v ]
out += [ "end subroutine" ]
out = map(lambda x: "%s\n"%(x),out)
if not same_file(FILENAME,out):
file = open(FILENAME,'w')
file.writelines(out)
file.close()
if __name__ == '__main__':
create()

View File

@ -1,204 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import os,sys
import irpf90_t
from command_line import command_line
irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
FILENAME = "Makefile"
FILENAME_GITIGNORE = ".gitignore"
IRPF90_MAKE = "irpf90.make"
######################################################################
def create():
has_makefile = True
try:
file = open(FILENAME,"r")
except IOError:
has_makefile = False
if has_makefile:
return
file = open(FILENAME,"w")
t = """IRPF90 = irpf90 #-a -d
FC = gfortran
FCFLAGS= -O2 -ffree-line-length-none -I .
NINJA = ninja
AR = ar
RANLIB = ranlib
SRC=
OBJ=
LIB=
-include %s
export
%s: $(filter-out %s%%, $(wildcard */*.irp.f)) $(wildcard *.irp.f) $(wildcard *.inc.f) Makefile
\t$(IRPF90)
"""%(IRPF90_MAKE,IRPF90_MAKE,irpdir)
file.write(t)
file.close()
create_gitignore()
######################################################################
def create_gitignore():
has_makefile = True
try:
file = open(FILENAME_GITIGNORE,"r")
except IOError:
has_makefile = False
if has_makefile:
return
file = open(FILENAME_GITIGNORE,"w")
t = "\n".join([ irpdir, mandir, IRPF90_MAKE, 'irpf90_entities', 'tags' ])
file.write(t)
file.close()
######################################################################
def run_ninja():
import ninja
ninja.run()
######################################################################
def run_make():
from modules import modules
mod = []
for m in modules.values():
mod.append(m)
file = open(IRPF90_MAKE,'w')
result = ""
result += "FC+=-I %s "%(irpdir)
for i in command_line.include_dir:
result += "-I %s%s "%(irpdir,i)
result += "\n"
result += "SRC += %sirp_stack.irp.F90"%(irpdir)
result += " %sirp_touches.irp.F90"%(irpdir)
# result += " %sirp_checkpoint.irp.F90"%(irpdir)
if command_line.do_openmp:
result += " %sirp_locks.irp.F90"%(irpdir)
if command_line.do_profile:
result += " %sirp_profile.irp.F90"%(irpdir)
for m in mod:
result += " %s%s.irp.F90"%(irpdir,m.filename)
result += " %s%s.irp.module.F90"%(irpdir,m.filename)
print >>file, result
result = "OBJ_IRP = %sirp_stack.irp.o "%(irpdir)
for m in mod:
if not m.is_main:
result += " %s%s.irp.o"%(irpdir,m.filename)
result += " %s%s.irp.module.o"%(irpdir,m.filename)
print >>file, result
print >>file, "OBJ1 = $(OBJ_IRP) $(OBJ) %sirp_touches.irp.o "%(irpdir),
# print >>file, " %sirp_checkpoint.irp.o"%(irpdir),
if command_line.do_profile:
print >>file, " %sirp_profile.irp.o"%(irpdir), " irp_rdtsc.o",
if command_line.do_codelet:
print >>file, " irp_rdtsc.o",
if command_line.do_openmp:
print >>file, " %sirp_locks.irp.o"%(irpdir)
else:
print >>file, ""
all = filter(lambda x: modules[x].is_main, modules)
all = map(lambda x: x[:-6], all)
all_o = map(lambda x: "%s.irp.module.o %s.irp.o"%(x,x), all)
print >>file, "ALL = %s"%(" ".join(all))
print >>file, "ALL_OBJ = %s"%(" ".join(all_o))
print >>file, "ALL_OBJ1 = $(patsubst %%, %s%%,$(notdir $(ALL_OBJ)))"%(irpdir)
print >>file, "all:$(ALL)"
print >>file, "\t@$(MAKE) -s move"
# print >>file, "ifdef USE_IRPF90_A"
for m in mod:
if m.is_main:
exe = m.filename
print >>file, "%s: %s%s.irp.o %s%s.irp.module.o IRPF90_temp/irpf90.a"%(exe,irpdir,exe,irpdir,exe)
print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o IRPF90_temp/irpf90.a $(LIB)"%(irpdir,irpdir)
print >>file, "\t@$(MAKE) -s move"
# print >>file, "else"
# for m in mod:
# if m.is_main:
# exe = m.filename
# print >>file, "%s: %s%s.irp.o %s%s.irp.module.o $(OBJ1)"%(exe,irpdir,exe,irpdir,exe)
# print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o $(OBJ1) $(LIB)"%(irpdir,irpdir)
# print >>file, "\t@$(MAKE) -s move"
# print >>file, "endif"
buffer = ""
for m in mod:
filename = "%s%s.irp.o: $(OBJ) %s%s.irp.module.o"%(irpdir,m.filename,irpdir,m.filename)
needed_modules = filter( lambda x: modules[x].name in m.needed_modules, modules )
needed_files = map(lambda x: modules[x].filename, needed_modules)
mds = map (lambda x: " %s%s.irp.module.o"%(irpdir,x),needed_files)
print >>file, filename," ".join(mds)," ".join(m.includes)
if not m.is_main:
buffer += "\t - @echo '"+filename+" ".join(mds)+"' >> %sdist_Makefile\n"%(irpdir)
# print >>file, "%sirp_touches.irp.o %sirp_checkpoint.irp.o: $(OBJ) "%(irpdir,irpdir),
print >>file, "%sirp_touches.irp.o: $(OBJ) "%(irpdir),
mds = filter(lambda x: not x.is_main,mod)
mds = map(lambda x: " %s%s.irp.o %s%s.irp.o"%(irpdir,x.filename,irpdir,x.filename),mds)
print >>file," ".join(mds)
if command_line.do_profile:
print >>file, "%sirp_profile.irp.o:"%(irpdir),
print >>file," ".join(mds)
if command_line.do_openmp:
print >>file, "%sirp_locks.irp.o:"%(irpdir),
print >>file," ".join(mds)
for dir in [ irpdir ] + map(lambda x: irpdir+x, command_line.include_dir):
print >>file, dir+"%.irp.module.o: $(OBJ) "+dir+"%.irp.module.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.module.F90 -o "+dir+"$*.irp.module.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.module.o "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.o: %.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c $*.F90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f90\n\t$(FC) $(FCFLAGS) -c $*.f90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f\n\t$(FC) $(FCFLAGS) -c $*.f -o "+dir+"$*.o"
print >>file, dir+"%.o: %.F\n\t$(FC) $(FCFLAGS) -c $*.F -o "+dir+"$*.o"
print >>file, dir+"%.irp.F90: "+IRPF90_MAKE+"\n"
print >>file, "move:\n\t@mv -f *.mod IRPF90_temp/ 2> /dev/null | DO_NOTHING=\n"
print >>file, "IRPF90_temp/irpf90.a: $(OBJ) $(OBJ1)\n\t$(AR) crf IRPF90_temp/irpf90.a $(OBJ1)\n"
print >>file, "clean:\n\trm -rf $(EXE) $(OBJ1) IRPF90_temp/irpf90.a $(ALL_OBJ1) $(ALL)\n"
print >>file, "veryclean:\n\t- $(MAKE) clean\n"
print >>file, "\t- rm -rf "+irpdir+" "+mandir+" "+IRPF90_MAKE+" irpf90_entities dist tags\n"
file.close()
######################################################################
def run():
if command_line.do_ninja:
run_ninja()
else:
run_make()

View File

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

View File

@ -1,68 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from irpf90_t import *
from parsed_text import parsed_text
from module import Fmodule
from util import *
######################################################################
def create_modules():
result = {}
for filename,text in parsed_text:
result[filename] = Fmodule(text,filename)
return result
modules = create_modules()
######################################################################
def write_module(m):
# Module data
filename = irpdir+m.filename+".irp.module.F90"
text = m.header + m.head
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):
# print filename
file = open(filename,"w")
file.writelines(text)
file.close()
# Subroutines
filename = irpdir+m.filename+".irp.F90"
text = m.header + m.generated_text + m.residual_text
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):
# print filename
file = open(filename,"w")
file.writelines(text)
file.close()
######################################################################
if __name__ == '__main__':
write_module(modules['psi.irp.f'])

View File

@ -1,408 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import os,sys
import irpf90_t
from command_line import command_line
from modules import modules
irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
irp_id = irpf90_t.irp_id
FILENAME = os.path.join(irpdir,"build.ninja")
cwd = os.getcwd()
PRINT_WIDTH=50
def dress(f,in_root=False):
"""
Transfoms the filename f into $PWD/IRPF90_temp/f
"""
if in_root:
result = os.path.join(cwd,f)
else:
result = os.path.join(cwd,irpdir,f)
return os.path.normpath(result)
def create_build_touches(list_of_other_o):
"""
Create the build command for the irp_touches.o file and the irpf90.a library.
"""
name = "irp_touches"
short_lib = "irpf90.a"
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
lib = dress(short_lib)
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules ]
list_of_modules = map(dress, needed_modules) + list_of_other_o
list_of_modules = ' '.join(list_of_modules)
result = '\n'.join(
[
"build {target_o}: compile_touches_{id} {target_F90} | {list_of_modules}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
"build {lib}: link_lib_{id} {target_o} {list_of_modules}",
" short_out = {short_lib}",
"",
] )
result = result.format(
id = irp_id ,
lib = lib ,
list_of_modules = list_of_modules ,
short_lib = short_lib ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_o = target_o
)
return result
def create_build_target(t,list_of_other_o):
"""
Create the build command for the target module t. t is a Fmodule object.
"""
name = t.filename
irp_lib = dress("irpf90.a")
target = dress(name,in_root=True)
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
short_target_module_F90 = "%s.irp.module.F90"%name
short_target_module_o = "%s.irp.module.o"%name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
target_module_o = dress(short_target_module_o)
target_module_F90 = dress(short_target_module_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules \
if modules[x].name in t.needed_modules ] + [ target_module_o ]
list_of_o = [ target_o, target_module_o, irp_lib ]
list_of_o = ' '.join(list_of_o)
list_of_modules = map(dress, needed_modules) + list_of_other_o
list_of_modules = ' '.join(list_of_modules)
list_of_includes = ' '.join(map(lambda x: dress(x,in_root=True), t.includes))
result = '\n'.join(
[ "build {target}: link_{id} {list_of_o}",
" short_out = {short_target}",
"",
"build {target_o}: compile_fortran_{id} {target_F90} | {list_of_modules} {list_of_includes}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
"build {target_module_o}: compile_fortran_{id} {target_module_F90}",
" short_in = {short_target_module_F90}",
" short_out = {short_target_module_o}",
"",
] )
result = result.format(
id = irp_id ,
list_of_includes = list_of_includes ,
list_of_modules = list_of_modules ,
list_of_o = list_of_o ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target_module_F90 = os.path.split(target_module_F90)[1] ,
short_target_module_o = os.path.split(target_module_o)[1] ,
short_target = name ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_module_F90 = target_module_F90 ,
target_module_o = target_module_o ,
target_o = target_o ,
target = target
)
return result
def create_build_non_target(t,list_of_other_o):
"""
Create the build command for the non-target module t. t is a Fmodule object.
"""
name = t.filename
target = dress(name,in_root=True)
short_target_o = "%s.irp.o"%name
short_target_F90 = "%s.irp.F90"%name
short_target_module_F90 = "%s.irp.module.F90"%name
short_target_module_o = "%s.irp.module.o"%name
target_o = dress(short_target_o)
target_F90 = dress(short_target_F90)
target_module_o = dress(short_target_module_o)
target_module_F90 = dress(short_target_module_F90)
needed_modules = [ "%s.irp.module.o"%(modules[x].filename) for x in modules \
if modules[x].name in t.needed_modules ] + [ target_module_o ]
list_of_modules = map(dress, needed_modules)
list_of_modules = ' '.join(list_of_modules)
list_of_externals = ' '.join([ dress(x,in_root=True) for x in list_of_other_o ])
list_of_includes = ' '.join(map(lambda x: dress(x,in_root=True), t.includes))
result = '\n'.join(
[
"build {target_o}: compile_fortran_{id} {target_F90} | {list_of_modules} {list_of_externals}",
" short_in = {short_target_F90}",
" short_out = {short_target}",
"",
"build {target_module_o}: compile_fortran_{id} {target_module_F90} | {list_of_externals} {list_of_includes}",
" short_in = {short_target_F90}",
" short_out = {short_target_o}",
"",
] )
result = result.format(
id = irp_id ,
list_of_externals = list_of_externals ,
list_of_includes = list_of_includes ,
list_of_modules = list_of_modules ,
short_target_F90 = os.path.split(target_F90)[1] ,
short_target = name ,
short_target_o = os.path.split(target_o)[1] ,
target_F90 = target_F90 ,
target_module_F90 = target_module_F90 ,
target_module_o = target_module_o ,
target_o = target_o
)
return result
def create_build_remaining(f):
"""
Create the build command for the remaining file f. f is a file name (str).
"""
t, extension = f.rsplit('.',1)
t1 = dress(t,in_root=True)
t2 = dress(t,in_root=False)
target_i = f
target_o = "%s.o"%t
if not target_o.startswith(os.path.join(cwd,irpdir)):
target_o = target_o.replace(cwd,os.path.join(cwd,irpdir))
if extension.lower() in [ 'f', 'f90' ]:
result = [ "build {target_o}: compile_fortran_{id} {target_i}" ]
elif extension.lower() in [ 'c' ]:
result = [ "build {target_o}: compile_c_{id} {target_i}" ]
elif extension.lower() in [ 'cxx', 'cpp' ]:
result = [ "build {target_o}: compile_cxx_{id} {target_i}" ]
result += [ " short_in = {short_target_i}",
" short_out = {short_target_o}", "" ]
result = '\n'.join(result).format(
target_o = target_o,
target_i = target_i,
short_target_o = os.path.split(target_o)[1],
short_target_i = os.path.split(target_i)[1],
id = irp_id
)
return result
def create_irpf90_make(targets):
targets = ' '.join(targets)
result = """NINJA += -C {0}
TARGETS={1}
.PHONY: all clean veryclean
all:
$(NINJA)
$(TARGETS):
$(NINJA) $(PWD)/$@
clean:
$(NINJA) -t clean
veryclean: clean
rm -rf IRPF90_temp/ IRPF90_man/ irpf90.make irpf90_entities dist tags
""".format(irpdir, targets)
import makefile
with open(makefile.IRPF90_MAKE,'w') as file:
file.write(result)
def run():
output = [ "builddir = %s"%os.path.join(cwd,irpdir) ]
# Environment variables
try: FC = os.environ["FC"]
except KeyError: FC="gfortran -ffree-line-length-none"
try: AR = os.environ["AR"]
except KeyError: AR="ar"
try: CC = os.environ["CC"]
except KeyError: CC="gcc"
try: CXX = os.environ["CXX"]
except KeyError: CXX="g++"
includes = [ "-I %s"%(i) for i in command_line.include_dir ]
FC += " "+' '.join(includes)
CC += " "+' '.join(includes)
CXX += " "+' '.join(includes)
try: SRC = os.environ["SRC"].split()
except KeyError: SRC=[]
try: OBJ = os.environ["OBJ"].split()
except KeyError: OBJ=[]
try: LIB = os.environ["LIB"].split()
except KeyError: LIB=[]
try: FCFLAGS = os.environ["FCFLAGS"].split()
except KeyError: FCFLAGS = [ "-O2" ]
try: CFLAGS = os.environ["CFLAGS"].split()
except KeyError: CFLAGS = [ "-O2" ]
try: CXXFLAGS = os.environ["CXXFLAGS"].split()
except KeyError: CXXFLAGS = [ "-O2" ]
FCFLAGS = ' '.join(FCFLAGS)
CFLAGS = ' '.join(CFLAGS)
CXXFLAGS = ' '.join(CXXFLAGS)
LIB = ' '.join(LIB)
# Rules
t = [ "rule compile_fortran_{id}",
" command = {FC} {FCFLAGS} -c $in -o $out",
" description = F : $short_in -> $short_out",
"",
"rule compile_touches_{id}",
" command = {FC} -c $in -o $out",
" description = F : $short_in -> $short_out",
"",
"",
"rule compile_c_{id}" ,
" command = {CC} {CFLAGS} -c $in -o $out",
" description = C : $short_in -> $short_out",
"",
"rule compile_cxx_{id}",
" command = {CXX} {CXXFLAGS} -c $in -o $out",
" description = C++ : $short_in -> $short_out",
"",
"rule link_lib_{id}",
" command = {AR} crf $out $in" ,
" description = Link: $short_out",
"",
"rule link_{id}",
" command = {FC} $in {LIB} -o $out" ,
" description = Link: $short_out"]
output += [ '\n'.join(t).format(id=irp_id, FC=FC, FCFLAGS=FCFLAGS, LIB=LIB, CXX=CXX, CXXFLAGS=CXXFLAGS, CC=CC, CFLAGS=CFLAGS, AR=AR) ]
# All modules : list of Fmodule objects
l_mod = list( modules.values() )
# Modules that are not targets
l_non_targets = [ x for x in l_mod if not x.is_main ]
# Common object/source files
l_common_o = [ "irp_touches.irp.o" ] + \
[ "{0}.irp.o".format(x.filename) for x in l_non_targets ] + \
[ "{0}.irp.module.o".format(x.filename) for x in l_non_targets ]
l_common_s = []
if command_line.do_assert:
l_common_o += [ "irp_stack.irp.o" ]
l_common_s += [ "irp_stack.irp.F90" ]
if command_line.do_openmp:
l_common_o += [ "irp_locks.irp.o" ]
l_common_s += [ "irp_locks.irp.F90" ]
if command_line.do_profile:
l_common_o += [ "irp_profile.irp.o", "irp_rdtsc.o" ]
l_common_s += [ "irp_profile.irp.F90", "irp_rdtsc.c" ]
l_common_o = map(dress,l_common_o) + map(lambda x: dress(x,in_root=True), OBJ)
l_common_s = map(dress,l_common_s) + map(lambda x: dress(x,in_root=True), SRC)
# IRP_touches
output.append(create_build_touches(l_common_o[1:]))
# All targets : list of Fmodule objects
l_targets = [ x for x in l_mod if x.is_main ]
# Create lines
for i in l_non_targets:
output.append (create_build_non_target(i,OBJ))
for i in l_targets:
output.append(create_build_target(i, l_common_o))
# Remaining files
for i in l_common_s:
output.append(create_build_remaining(i))
with open(FILENAME,'w') as f:
f.write('\n\n'.join(output))
f.write('\n')
create_irpf90_make([ x.filename for x in l_targets ] + [ os.path.join(irpdir,'irpf90.a') ] )
return

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

104
src/routine.py Normal file
View File

@ -0,0 +1,104 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from irpf90_t import *
from util import logger
try:
import irpy
except:
import lib_irpy as irpy
class Routine(object):
'''
A collection of list corresponding of a Routine (Subroutine, or function)
'''
############################################################
def __init__(self,text):
assert type(text) == list
assert len(text) > 0
self.text = text
self.prototype = self.text[0]
assert isinstance(self.prototype, (Subroutine, Function))
############################################################
@irpy.lazy_property_mutable
def called_by(self):
raise AttributeError
############################################################
@irpy.lazy_property
def name(self):
'''Name is lowercase'''
return self.prototype.subname
############################################################
@irpy.lazy_property
def is_function(self):
return "function" in self.prototype.lower
############################################################
@irpy.lazy_property
def is_subroutine(self):
return "subroutine" in self.prototype.lower
############################################################
@irpy.lazy_property
def doc(self):
l_doc = [ l for l in self.text if isinstance(l,Doc) ]
if not l_doc:
logger.info("Subroutine '%s' is not documented"%(self.name))
return [l.text.lstrip()[1:] for l in l_doc]
############################################################
@irpy.lazy_property
def touches_my_self(self):
return set(x for line in self.text for x in line.text.split()[1:] if isinstance(line,(Touch, SoftTouch)))
@irpy.lazy_property_mutable
def touches_ancestor(self):
raise AttributeError
@irpy.lazy_property
def touches(self):
return list(self.touches_my_self.union(self.touches_ancestor))
############################################################
@irpy.lazy_property
def regexp(self):
import re
return re.compile(r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
############################################################
@irpy.lazy_property
def calls(self):
return set(line.text.split('(',1)[0].split()[1].lower() for line in self.text if isinstance(line,Call))

View File

@ -1,131 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from irpf90_t import *
from util import *
import error
class Sub(object):
############################################################
def __init__(self,text):
assert type(text) == list
assert len(text) > 0
assert type(text[0]) in [Subroutine, Function]
self.text = text
self.called_by = []
############################################################
def name(self):
'''Name is lowercase'''
if '_name' not in self.__dict__:
self._name = find_subname(self.line)
return self._name
name = property(name)
############################################################
def is_function(self):
if '_is_function' not in self.__dict__:
self._is_function = "function" in self.line.lower
return self._is_function
is_function = property(is_function)
############################################################
def doc(self):
if '_doc' not in self.__dict__:
def f(l): return
buffer = filter(lambda l:type(l) == Doc, self.text)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Subroutine %s is not documented"%(self.name))
return self._doc
doc = property(doc)
############################################################
def line(self):
if '_line' not in self.__dict__:
self._line = self.text[0]
return self._line
line = property(line)
############################################################
def touches(self):
if '_touches' not in self.__dict__:
from subroutines import subroutines
self._touches = []
for line in filter(lambda x: type(x) in [Touch, SoftTouch],self.text):
self._touches += line.text.split()[1:]
for sub in self.calls:
if sub in subroutines:
self._touches += subroutines[sub].touches
self._touches = make_single(self._touches)
return self._touches
touches = property(touches)
############################################################
def needs(self):
if '_needs' not in self.__dict__:
import parsed_text
self._needs = make_single(self._needs)
return self._needs
needs = property(needs)
############################################################
def to_provide(self):
if '_to_provide' not in self.__dict__:
import parsed_text
return self._to_provide
to_provide = property(to_provide)
############################################################
def regexp(self):
if '_regexp' not in self.__dict__:
import re
self._regexp = re.compile( \
r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
return self._regexp
regexp = property(regexp)
############################################################
def calls(self):
if '_calls' not in self.__dict__:
buffer = filter(lambda x: type(x) == Call,self.text)
self._calls = []
for line in buffer:
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
self._calls = make_single(self._calls)
return self._calls
calls = property(calls)
######################################################################
if __name__ == '__main__':
from preprocessed_text import preprocessed_text
from variables import variables
from subroutines import subroutines
print map(lambda x: variables[x].needs, subroutines['full_ci'].needs)
print subroutines['full_ci'].calls

View File

@ -1,72 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from util import *
from subroutine import *
from variables import variables
from variable import Variable
from irpf90_t import *
def create_subroutines():
from preprocessed_text import preprocessed_text
result = {}
for filename, text in preprocessed_text:
buffer = []
inside = False
for line in text:
if type(line) in [ Subroutine, Function ]:
inside = True
if inside:
buffer.append(line)
if isinstance(line,End):
if inside:
v = Sub(buffer)
result[v.name] = v
buffer = []
inside = False
return result
def create_called_by(subs,vars):
for s in subs.values() + vars.values():
if type(s) == Variable and s.same_as != s.name:
continue
for x in s.calls:
try:
subs[x].called_by.append(s.name)
except KeyError:
pass
for s in subs.values():
s.called_by = make_single(s.called_by)
s.called_by.sort()
subroutines = create_subroutines()
create_called_by(subroutines,variables)
if __name__ == '__main__':
for v in subroutines.keys():
print v

View File

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

View File

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

View File

@ -1,697 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from irpf90_t import *
from util import *
import error
from command_line import command_line
class Variable(object):
############################################################
def __init__(self,text,label,name = None):
assert type(text) == list
assert len(text) > 0
assert type(text[0]) == Begin_provider
self.label = label
self.text = text
if name is not None:
self._name = name
############################################################
def is_touched(self):
if '_is_touched' not in self.__dict__:
from variables import variables
result = self.is_read
for i in self.children:
if variables[i].is_touched:
result = True
break
self._is_touched = result
return self._is_touched
is_touched = property(is_touched)
############################################################
def has_openmp(self):
if '_has_openmp' not in self.__dict__:
self._has_openmp = False
self.builder()
return self._has_openmp
has_openmp = property(has_openmp)
############################################################
def is_written(self):
if '_is_written' not in self.__dict__:
from variables import variables
result = False
for i in self.parents:
if variables[i].is_written:
result = True
break
self._is_written = result
return self._is_written
is_written = property(is_written)
############################################################
def is_read(self):
if '_is_read' not in self.__dict__:
from variables import variables
result = False
for i in self.parents:
if variables[i].is_read:
result = True
break
self._is_read = result
return self._is_read
is_read = property(is_read)
############################################################
def is_main(self):
if '_is_main' not in self.__dict__:
self._is_main = (self.name == self.same_as)
return self._is_main
is_main = property(is_main)
############################################################
def name(self):
'''Name is lowercase'''
if '_name' not in self.__dict__:
buffer = None
text = self.text
for line in text:
if type(line) == Begin_provider:
self._name = line.filename[1]
break
return self._name
name = property(name)
############################################################
def doc(self):
if '_doc' not in self.__dict__:
text = self.text
buffer = filter(lambda l:type(l) == Doc, text)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Variable %s is not documented"%(self.name))
return self._doc
doc = property(doc)
############################################################
def documented(self):
if '_documented' not in self.__dict__:
self._documented = (self.doc != [])
return self._documented
documented = property(documented)
############################################################
def includes(self):
if '_includes' not in self.__dict__:
self._includes = []
text = self.text
for line in filter(lambda x: type(x) == Include,text):
self._includes.append(line.filename)
make_single(self._includes)
return self._includes
includes = property(includes)
############################################################
def calls(self):
if '_calls' not in self.__dict__:
self._calls = []
text = self.text
for line in filter(lambda x: type(x) == Call,text):
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
make_single(self._calls)
return self._calls
calls=property(fget=calls)
############################################################
def others(self):
if '_others' not in self.__dict__:
result = []
append = result.append
f = lambda l: type(l) in [Begin_provider, Cont_provider]
text = self.text
lines = filter(f, text)
for line in lines:
append(line.filename[1])
result.remove(self.name)
self._others = result
return self._others
others = property(others)
############################################################
def same_as(self):
if '_same_as' not in self.__dict__:
if type(self.line) == Begin_provider:
result = self.name
else:
result = self.text[0].filename[1]
self._same_as = result
return self._same_as
same_as = property(same_as)
############################################################
def allocate(self):
if '_allocate' not in self.__dict__:
if not self.is_main:
self._allocate = []
else:
from variables import variables
def f(var):
return variables[var].dim != []
self._allocate = filter ( f, self.others + [self.name] )
return self._allocate
allocate = property(allocate)
############################################################
def dim(self):
if '_dim' not in self.__dict__:
line = self.line.text.split('!')[0]
buffer = line.replace(']','').split(',',2)
if len(buffer) == 2:
self._dim = []
else:
buffer = buffer[2].strip()[1:-1].split(',')
self._dim = map(strip,buffer)
return self._dim
dim = property(dim)
############################################################
def type(self):
if '_type' not in self.__dict__:
line = self.line.text
buffer = line.split(',')[0]
try:
buffer = buffer.split('[')[1].strip()
except IndexError:
error.fail(None,"Error in definition of %s."%(self.name))
if self.dim != []:
buffer = "%s, allocatable"%(buffer)
self._type = buffer
return self._type
type = property(type)
############################################################
def fmodule(self):
if '_fmodule' not in self.__dict__:
self._fmodule = self.line.filename[0].replace('/','__').split('.irp.f')[0]+'_mod'
return self._fmodule
fmodule = property(fmodule)
############################################################
def regexp(self):
if '_regexp' not in self.__dict__:
import re
self._regexp = re.compile( \
r"([^a-z0-9'\"_]|^)%s([^a-z0-9_]|$)"%(self.name),re.I)
return self._regexp
regexp = property(regexp)
############################################################
def line(self):
if '_line' not in self.__dict__:
f = lambda l: type(l) in [Begin_provider, Cont_provider]
text = self.text
lines = filter(f, text)
for line in lines:
buffer = line.filename[1]
if self._name == buffer:
self._line = line
break
assert '_line' in self.__dict__
return self._line
line = property(line)
############################################################
def header(self):
if '_header' not in self.__dict__:
name = self.name
self._header = [ " %s :: %s %s"%(self.type, name, build_dim_colons(self) ) ]
if command_line.coarray:
if self.dim == []:
self._header[0] += " [*]"
else:
self._header[0] += " [:]"
if self.dim != [] and command_line.align != '1':
self._header += [" !DIR$ ATTRIBUTES ALIGN: %s :: %s"%(command_line.align,name)]
if self.is_main:
self._header += [ " logical :: %s_is_built = .False."%(name) ]
return self._header
header = property(header)
############################################################
def toucher(self):
if '_toucher' not in self.__dict__:
if not self.is_main:
self._toucher = []
else:
from modules import modules
from variables import variables
if '_needed_by' not in self.__dict__:
import parsed_text
parents = self.parents
parents.sort()
mods = map(lambda x: variables[x].fmodule, parents)
mods = make_single(mods)+[self.fmodule]
name = self.name
result = [ "subroutine touch_%s"%(name) ]
result += map(lambda x: " Use %s"%(x),mods)
result.append(" implicit none")
if command_line.do_debug:
length = str(len("touch_%s"%(name)))
result += [ " character*(%s) :: irp_here = 'touch_%s'"%(length,name) ]
if command_line.do_debug:
result += [ " call irp_enter(irp_here)" ]
result += map( lambda x: " %s_is_built = .False."%(x), parents)
result.append(" %s_is_built = .True."%(name))
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine touch_%s"%(name))
result.append("")
self._toucher = result
return self._toucher
toucher = property(toucher)
##########################################################
def locker(self):
if '_locker' not in self.__dict__:
if not command_line.do_openmp:
self._locker = []
else:
from modules import modules
from variables import variables
name = self.name
result = [ "subroutine irp_lock_%s(set)"%(name) ]
result += [ " use omp_lib",
" implicit none",
" logical, intent(in) :: set",
" integer(kind=omp_nest_lock_kind),save :: %s_lock"%(name),
" integer,save :: ifirst",
]
if command_line.do_debug:
length = str(len("irp_lock_%s"%(name)))
result += [ " character*(%s) :: irp_here = 'irp_lock_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += [ " if (ifirst == 0) then",
" ifirst = 1",
" call omp_init_nest_lock(%s_lock)"%(name),
" endif",
" if (set) then",
" call omp_set_nest_lock(%s_lock)"%(name),
" else",
" call omp_unset_nest_lock(%s_lock)"%(name),
" endif",
]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine irp_lock_%s"%(name))
result.append("")
self._locker = result
return self._locker
locker = property(locker)
##########################################################
def reader(self):
if '_reader' not in self.__dict__:
if not self.is_main:
self._reader = []
else:
if '_needs' not in self.__dict__:
import parsed_text
from variables import variables
name = self.name
result = [ \
"subroutine reader_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("reader_%s"%(self.name))
result += [\
" character*(%d) :: irp_here = 'reader_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += map(lambda x: " call reader_%s(irp_num)"%(x),self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo"]
for n in [ name ]+self.others:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='OLD',action='READ')"%(n),
" read(irp_iunit,*) %s%s"%(n,build_dim_colons(variables[n])),
" close(irp_iunit)" ]
result += [ \
" call touch_%s"%(name),
" %s_is_built = .True."%(name) ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine reader_%s"%(name))
result.append("")
self._reader = result
return self._reader
reader = property(reader)
##########################################################
def writer(self):
if '_writer' not in self.__dict__:
if not self.is_main:
self._writer = []
else:
from variables import variables
if '_needs' not in self.__dict__:
import parsed_text
name = self.name
result = [ \
"subroutine writer_%s(irp_num)"%(name),
" use %s"%(self.fmodule),
" implicit none",
" character*(*), intent(in) :: irp_num",
" logical :: irp_is_open",
" integer :: irp_iunit" ]
if command_line.do_debug:
length = len("writer_%s"%(self.name))
result += [\
" character*(%d) :: irp_here = 'writer_%s'"%(length,name),
" call irp_enter(irp_here)" ]
result += [ \
" if (.not.%s_is_built) then"%(self.same_as),
" call provide_%s"%(self.same_as),
" endif" ]
result += map(lambda x: " call writer_%s(irp_num)"%(x),self.needs)
result += [ \
" irp_is_open = .True.",
" irp_iunit = 9",
" do while (irp_is_open)",
" irp_iunit = irp_iunit+1",
" inquire(unit=irp_iunit,opened=irp_is_open)",
" enddo" ]
for n in [ name ] + self.others:
result += [\
" open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='UNKNOWN',action='WRITE')"%(n),
" write(irp_iunit,*) %s%s"%(n,build_dim_colons(variables[n])),
" close(irp_iunit)" ]
if command_line.do_debug:
result.append(" call irp_leave(irp_here)")
result.append("end subroutine writer_%s"%(name))
result.append("")
self._writer = result
return self._writer
writer = property(writer)
##########################################################
def free(self):
if '_free' not in self.__dict__:
name = self.name
result = [ "!","! >>> FREE %s"%(name),
" %s_is_built = .False."%(self.same_as) ]
if self.dim != []:
if command_line.do_memory:
result += [ \
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name),
" print *, 'Deallocating %s'"%(name),
" endif" ]
else:
result += [ \
" if (allocated(%s)) then"%(name),
" deallocate (%s)"%(name),
" endif" ]
result.append("! <<< END FREE")
self._free = result
return self._free
free = property(free)
##########################################################
def provider(self):
if '_provider' not in self.__dict__:
if not self.is_main:
self._provider = []
else:
if '_to_provide' not in self.__dict__:
import parsed_text
from variables import variables, build_use, call_provides
name = self.name
same_as = self.same_as
def build_alloc(name):
self = variables[name]
if self.dim == []:
return []
def do_size():
result = " print *, ' size: ("
result += ','.join(self.dim)
return result+")'"
def check_dimensions():
result = map(lambda x: "(%s>0)"%(dimsize(x)), self.dim)
result = ".and.".join(result)
result = " if (%s) then"%(result)
return result
def dimensions_OK():
result = [ " irp_dimensions_OK = .True." ]
for i,k in enumerate(self.dim):
result.append(" irp_dimensions_OK = irp_dimensions_OK.AND.(SIZE(%s,%d)==(%s))"%(name,i+1,dimsize(k)))
return result
def do_allocate():
if command_line.coarray:
result = " allocate(%s(%s)[*],stat=irp_err)"
else:
result = " allocate(%s(%s),stat=irp_err)"
result = result%(name,','.join(self.dim))
if command_line.do_memory:
tmp = "\n print *, %s, 'Allocating %s(%s)'"
d = ','.join(self.dim)
result += tmp%('size('+name+')',name,d)
return result
result = [ " if (allocated (%s) ) then"%(name) ]
result += dimensions_OK()
result += [\
" if (.not.irp_dimensions_OK) then",
" deallocate(%s,stat=irp_err)"%(name),
" if (irp_err /= 0) then",
" print *, irp_here//': Deallocation failed: %s'"%(name),
do_size(),
" endif"]
if command_line.do_memory:
result += [\
" print *, 'Deallocating %s'"%(name) ]
result.append(check_dimensions())
result.append(do_allocate())
result += [\
" if (irp_err /= 0) then",
" print *, irp_here//': Allocation failed: %s'"%(name),
do_size(),
" endif",
" endif",
" endif",
" else" ]
result.append(check_dimensions())
result.append(do_allocate())
result += [\
" if (irp_err /= 0) then",
" print *, irp_here//': Allocation failed: %s'"%(name),
do_size(),
" endif",
" endif",
" endif" ]
return result
result = []
if command_line.directives and command_line.inline in ["all","providers"]:
result += [ "!DEC$ ATTRIBUTES FORCEINLINE :: provide_%s"%(name) ]
result += [ "subroutine provide_%s"%(name) ]
result += build_use( [same_as]+self.to_provide )
if command_line.do_openmp:
result += [" use omp_lib"]
result.append(" implicit none")
length = len("provide_%s"%(name))
result += [\
" character*(%d) :: irp_here = 'provide_%s'"%(length,name),
" integer :: irp_err ",
" logical :: irp_dimensions_OK",
"!$ integer :: nthreads"]
if command_line.do_openmp:
result.append(" call irp_lock_%s(.True.)"%(same_as))
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_enter(irp_here)")
result += call_provides(self.to_provide)
result += flatten( map(build_alloc,[self.same_as]+self.others) )
result += [ " if (.not.%s_is_built) then"%(same_as),
" call bld_%s"%(same_as),
" %s_is_built = .True."%(same_as), "" ]
result += [ " endif" ]
if command_line.do_assert or command_line.do_debug:
result.append(" call irp_leave(irp_here)")
if command_line.do_openmp:
result.append(" call irp_lock_%s(.False.)"%(same_as))
result.append("end subroutine provide_%s"%(name) )
result.append("")
self._provider = result
return self._provider
provider = property(provider)
##########################################################
def builder(self):
if '_builder' not in self.__dict__:
if not self.is_main:
self._builder = []
else:
import parsed_text
from variables import build_use, call_provides
for filename,buffer in parsed_text.parsed_text:
if self.line.filename[0].startswith(filename):
break
text = []
same_as = self.same_as
inside = False
for vars,line in buffer:
if type(line) == Begin_provider:
if line.filename[1] == same_as:
inside = True
vars = []
if inside:
text.append( (vars,line) )
text += map( lambda x: ([],Simple_line(line.i,x,line.filename)), call_provides(vars) )
if command_line.do_profile and type(line) == Begin_provider:
text.append( ( [], Declaration(line.i," double precision :: irp_rdtsc, irp_rdtsc1, irp_rdtsc2",line.filename) ) )
text.append( ( [], Simple_line(line.i," irp_rdtsc1 = irp_rdtsc()",line.filename) ) )
if type(line) == End_provider:
if inside:
break
name = self.name
text = parsed_text.move_to_top(text,Declaration)
text = parsed_text.move_to_top(text,Implicit)
text = parsed_text.move_to_top(text,Use)
text = map(lambda x: x[1], text)
# inside_omp = False
for line in filter(lambda x: type(x) not in [ Begin_doc, End_doc, Doc], text):
if type(line) == Begin_provider:
result = []
if command_line.directives and command_line.inline in ["all","builders"]:
result += [ "!DEC$ ATTRIBUTES INLINE :: bld_%s"%(same_as) ]
result += [ "subroutine bld_%s"%(name) ]
result += build_use([name]+self.needs)
elif type(line) == Cont_provider:
pass
elif type(line) == End_provider:
if command_line.do_profile:
result += [ " irp_rdtsc2 = irp_rdtsc()" ,
" call irp_set_timer(%d,(irp_rdtsc2-irp_rdtsc1))"%self.label ]
result.append( "end subroutine bld_%s"%(name) )
break
elif type(line) == Openmp:
# Detect OpenMP blocks
buffer = line.text.lower().split()
if buffer[1] == "parallel":
# inside_omp = True
self._has_openmp = True
# if buffer[1] == "end" and buffer[2] == "parallel":
# inside_omp = False
result.append(line.text)
else:
# if inside_omp:
# if type(line) in [ Provide_all, Provide, Touch, SoftTouch ]:
# error.fail(line,str(type(line))+"is not allowed in an OpenMP block.")
result.append(line.text)
self._builder = result
return self._builder
builder = property(builder)
##########################################################
def children(self):
if '_children' not in self.__dict__:
if not self.is_main:
self._children = []
from variables import variables
if '_needs' not in self.__dict__:
import parsed_text
result = []
for x in self.needs:
result.append(x)
try:
result += variables[x].children
except RuntimeError:
pass # Exception will be checked after
self._children = make_single(result)
if self.name in result:
error.fail(self.line,"Cyclic dependencies:\n%s"%(str(self._children)))
return self._children
children = property(children)
##########################################################
def parents(self):
if '_parents' not in self.__dict__:
if not self.is_main:
self._parents = []
else:
from variables import variables
if '_needed_by' not in self.__dict__:
import parsed_text
result = []
for x in self.needed_by:
result.append(x)
try:
result += variables[x].parents
except RuntimeError:
pass # Exception will be checked after
self._parents = make_single(result)
if self.name in result:
error.fail(self.line,"Cyclic dependencies:\n%s"%(str(self._parents)))
return self._parents
parents = property(parents)
######################################################################
if __name__ == '__main__':
from preprocessed_text import preprocessed_text
from variables import variables
#for v in variables.keys():
# print v
def print_dot(x,done):
if x.children == []:
return
for i in x.needs:
pair = (x.name, i)
if pair not in done:
print "%s -> %s"%( x.name, i )
done[pair] = None
print_dot(variables[i],done)
print "digraph G { "
# print_dot(variables['e_loc'], {})
print_dot(variables['psi_value'], {})
print "}"

View File

@ -1,96 +0,0 @@
#!/usr/bin/env python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
from variable import *
from irpf90_t import *
from command_line import command_line
from util import *
######################################################################
def create_variables():
from preprocessed_text import preprocessed_text
result = {}
icount = 0
for filename, text in preprocessed_text:
buffer = []
inside = False
for line in text:
if type(line) == Begin_provider:
inside = True
if inside:
buffer.append(line)
if type(line) == End_provider:
inside = False
icount += 1
v = Variable(buffer,icount)
if v.name in result:
print "Warning: Duplicate provider for %s in"%(v.name)
print "- ", v.line.filename[0], " line ", v.line.i
print "- ", result[v.name].line.filename[0], " line ", result[v.name].line.i
print "Choosing first version"
result[v.name] = v
for other in v.others:
if other in result:
print "Warning: Duplicate provider for %s in"%(other)
print "- ", v.line.filename[0], " line ", v.line.i
print "- ", result[other].line.filename[0], " line ", result[other].line.i
print "Choosing first version"
result[other] = Variable(buffer,icount,other)
buffer = []
return result
variables = create_variables()
######################################################################
def build_use(vars):
result = map(lambda x: " use %s"%(variables[x].fmodule), vars)
result = make_single(result)
return result
######################################################################
def call_provides(vars,opt=False):
vars = make_single( map(lambda x: variables[x].same_as, vars) )
if opt:
all_children = flatten( map(lambda x: variables[x].children, vars ))
vars = filter(lambda x: x not in all_children,vars)
def fun(x):
result = []
result += [ \
" if (.not.%s_is_built) then"%(x) ]
result += [ \
" call provide_%s"%(x) ]
result += [ \
" endif" ]
return result
result = flatten ( map (fun, vars) )
return result
######################################################################
if __name__ == '__main__':
for v in variables.keys():
print v

View File

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