From 7a2346023eec2e0c7ac3bb84d0b5600c7977a058 Mon Sep 17 00:00:00 2001 From: Anthony Scemama Date: Tue, 8 Sep 2009 16:00:46 +0200 Subject: [PATCH] Added allocation Version:1.1.6 --- src/create_man.py | 8 +- src/error.py | 4 +- src/module.py | 70 +++++++++++++++ src/modules.py | 21 +++++ src/util.py | 36 ++++++-- src/variable.py | 213 ++++++++++++++++++++++++++++++++++++++++++++-- src/variables.py | 20 +++++ src/version.py | 2 +- 8 files changed, 352 insertions(+), 22 deletions(-) create mode 100644 src/module.py create mode 100644 src/modules.py diff --git a/src/create_man.py b/src/create_man.py index c80a229..a133e90 100644 --- a/src/create_man.py +++ b/src/create_man.py @@ -3,10 +3,8 @@ from variable import Variable from variables import variables from irpf90_t import * +from util import * -def do_size(l): - if l == []: return "" - else: return "(%s)"%(",".join(l)) def do_print_short(file,var): assert isinstance(var,Variable) @@ -14,7 +12,7 @@ def do_print_short(file,var): var.line.filename, var.type, var.name, - do_size(var.dim) ) + build_dim(var.dim) ) ###################################################################### def process_doc(file,line): @@ -38,7 +36,7 @@ def process_types(file,var): name = var var = variables[var] type = var.type - dim = do_size(var.dim) + dim = build_dim(var.dim) print >>file, "%s\t:: %s\t%s"%(type,name,dim) ###################################################################### diff --git a/src/error.py b/src/error.py index a0b6112..aa8de3f 100644 --- a/src/error.py +++ b/src/error.py @@ -5,21 +5,21 @@ from irpf90_t import * ###################################################################### def fail(line,message): - assert isinstance(line,Line) 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): - assert isinstance(line,Line) if line is not None: + assert isinstance(line,Line) print """ Warning: ------- diff --git a/src/module.py b/src/module.py new file mode 100644 index 0000000..4238c44 --- /dev/null +++ b/src/module.py @@ -0,0 +1,70 @@ +#!/usr/bin/python + +from irpf90_t import * +from variable import * +from variables import variables + +class Fmodule(object): + + def __init__(self,text,filename): + self.text = text + self.name = "%s_mod"%(filename[:-6].lower()) + + def is_main(self): + if '_is_main' not in self.__dict__: + buffer = filter(lambda x: isinstance(x[1],Program),self.text) + self._is_main = (buffer != []) + return self._is_main + is_main = property(is_main) + + 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) + + def head(self): + if '_head' not in self.__dict__: + self._head = None + return self._head + head = property(head) + + def needed_vars(self): + if '_needed_vars' not in self.__dict__: + result = map(lambda x: variables[x].needs,self.variables) + result = make_single ( flatten(result) ) + self._needed_vars = result + return self._needed_vars + needed_vars = property(needed_vars) + + def generated_text(self): + if '_generated_text' not in self.__dict__: + self._generated_text = None + return self._generated_text + generated_text = property(generated_text) + + def residual_text(self): + if '_residual_text' not in self.__dict__: + self._residual_text = None + return self._residual_text + residual_text = property(residual_text) + + def needed_modules(self): + if '_needed_modules' not in self.__dict__: + buffer = filter(lambda x: isinstance(x,Use), self.generated_text) + buffer = map(lambda x: x.text.split()[1].lower(), buffer) + self._needed_modules = make_single(buffer) + return self._needed_modules + needed_modules = property(needed_modules) + +if __name__ == '__main__': + from parsed_text import parsed_text + for filename, text in parsed_text: + if filename == 'electrons.irp.f': + x = Fmodule(text,filename) + break + print x.needed_vars + print x.is_main + diff --git a/src/modules.py b/src/modules.py new file mode 100644 index 0000000..16aa3d1 --- /dev/null +++ b/src/modules.py @@ -0,0 +1,21 @@ +#!/usr/bin/python + +def modify_functions(): + result = [] + for filename,text in parsed_text: + begin = -1 + for i, (vars,line) in enumerate(text): + if type(line) in [ Subroutine, Function ]: + text[i] = [ text[i] ] + variable_list = list(vars) + begin = i + elif type(line) in [ End_provider, End ]: + text[begin].insert(1,map(lambda x: ([],x), build_use(variable_list))) + else: + variable_list += vars + text = flatten(text) + result.append ( (filename, text) ) + +def residual_text(): + pass + diff --git a/src/util.py b/src/util.py index d76403a..23075e8 100644 --- a/src/util.py +++ b/src/util.py @@ -57,12 +57,32 @@ def flatten(l): else: return [l] +def dimsize(x): + assert isinstance(x,str) + buffer = x.split(':') + if len(buffer) == 1: + return x + buffer = map(strip,buffer) + else: + assert len(buffer) == 2 + size = "" + b0, b1 = buffer + if b0.replace('-','').isdigit() and b1.replace('-','').isdigit(): + size = str( int(b1) - int(b0) + 1 ) + else: + if b0.replace('-','').isdigit(): + size = "%s - (%d)"%(b1,int(b0)-1) + elif b1.replace('-','').isdigit(): + size = "%d - %s"%(int(b1)+1,b0) + else: + size = "%s - %s + 1"%(b1,b0) + return size + if __name__ == '__main__': - a = 0 - print flatten(a) - a = [] - print flatten(a) - a = [1,2,3,4] - print flatten(a) - a = [1,2,3,[4,5,6,[7,8,9],10,],11,12,[13,14],15,16] - print flatten(a) + 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" + diff --git a/src/variable.py b/src/variable.py index a010b36..abecfc1 100644 --- a/src/variable.py +++ b/src/variable.py @@ -43,6 +43,13 @@ class Variable(object): 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 others(self): if '_others' not in self.__dict__: @@ -112,7 +119,7 @@ class Variable(object): ############################################################ def fmodule(self): if '_fmodule' not in self.__dict__: - self._fmodule = self.line.filename.replace('.irp.f','_mod') + self._fmodule = self.line.filename.split('.irp.f')[0]+'_mod' return self._fmodule fmodule = property(fmodule) @@ -173,17 +180,211 @@ class Variable(object): result += map( lambda x: "!DEC$ ATTRIBUTES FORCEINLINE :: touch_%s"%(x), self.needed_by ) result += map( lambda x: " call touch_%s"%(x), self.needed_by ) if command_line.do_debug: - result += [ " call irp_leave(irp_here)" ] - result += [ "end subroutine touch_%s"%(name) , "" ] + 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 reader(self): + if '_reader' not in self.__dict__: + if '_needs' not in self.__dict__: + import parsed_text + 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), parameter :: 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", + " open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='OLD',action='READ')"%(name), + " read(irp_iunit,*) %s%s"%(name,build_dim(self.dim)), + " close(irp_iunit)", + " call touch_%s"%(self.same_as), + " %s_is_built = .True."%(self.same_as) ] + 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 '_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), parameter :: 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", + " open(unit=irp_iunit,file='irpf90_%s_'//trim(irp_num),form='FORMATTED',status='UNKNOWN',action='WRITE')"%(name), + " write(irp_iunit,*) %s%s"%(name,build_dim(self.dim)), + " close(irp_iunit)" ] + result += map(lambda x: " call writer_%s(irp_num)"%(x),self.others) + 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 = [ \ + "subroutine free_%s"%(name), + " use %s"%(self.fmodule), + " implicit none" ] + if command_line.do_debug: + length = len("free_%s"%(self.name)) + result += [\ + " character*(%d), parameter :: irp_here = 'free_%s'"%(length,name), + " %s_is_built = .False."%(self.same_as) ] + if self.dim != []: + result += [ \ + " if (allocated(%s)) then"%(name), + " deallocate (%s)"%(name), + " endif" ] + if command_line.do_debug: + result.append(" call irp_leave(irp_here)") + result.append("end subroutine free_%s"%(name)) + result.append("") + self._free = result + return self._free + free = property(free) + + ########################################################## + def provider(self): + if '_provider' not in self.__dict__: + 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(): + result = " allocate(%s(%s),stat=irp_err)" + result = result%(name,','.join(self.dim)) + return result + + result = [ " if (allocated (%s) ) then"%(name) ] + result += dimensions_OK() + result += [\ + " if (.not.irp_dimensions_OK) then", + " deallocate(%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 = [ "subroutine provide_%s"%(name) ] + result += build_use( [same_as]+self.to_provide ) + result.append(" implicit none") + length = len("provide_%s"%(name)) + result += [\ + " character*(%d), parameter :: irp_here = 'provide_%s'"%(length,name), + " integer :: irp_err ", + " logical :: irp_dimensions_OK" ] + 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 += [\ + " call bld_%s"%(same_as), + " %s_is_built = .True."%(same_as), + "" ] + if command_line.do_assert or command_line.do_debug: + result.append(" call irp_leave(irp_here)") + result.append("end subroutine provide_%s"%(name) ) + result.append("") + self._provider = result + return self._provider + provider = property(provider) + ###################################################################### if __name__ == '__main__': from preprocessed_text import preprocessed_text from variables import variables - for v in variables.keys(): - print v - for line in variables['elec_coord'].toucher: + #for v in variables.keys(): + # print v + for line in variables['grid_eplf_aa'].provider: print line diff --git a/src/variables.py b/src/variables.py index 654207f..d2a04c3 100644 --- a/src/variables.py +++ b/src/variables.py @@ -2,7 +2,9 @@ from variable import * from irpf90_t import * +from util import * +###################################################################### def create_variables(): from preprocessed_text import preprocessed_text result = {} @@ -25,6 +27,24 @@ def create_variables(): 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): + vars = make_single( map(lambda x: variables[x].same_as, vars) ) + vars = map(lambda x: variables[x].name,vars) + def fun(x): + return [ \ + " if (.not.%s_is_built) then"%(x), + " call provide_%s"%(x), + " endif" ] + return flatten ( map (fun, vars) ) + +###################################################################### if __name__ == '__main__': for v in variables.keys(): print v diff --git a/src/version.py b/src/version.py index cc1ab03..366c449 100644 --- a/src/version.py +++ b/src/version.py @@ -1 +1 @@ -version = "1.1.5" +version = "1.1.6"