def ifcondcheck(condexpr, threshold): def get_nodes(node, bag, depth): if node and not hasattr(node, 'items'): bag['nodes'].append(node) bag = {'nodes': []} traverse(condexpr, get_nodes, bag) nodes = bag['nodes'] if len(nodes) > threshold: return True else: return False
def tokgen(self): from kgen_utils import traverse def get_edecl(node, bag, depth): from Fortran2003 import Entity_Decl if isinstance(node, Entity_Decl) and node.items[0].string == bag["name"]: bag["edecl"] = node.tostr() return True decls = self.entity_decls if hasattr(self, "new_entity_decls"): decls = [] for decl in self.new_entity_decls: edecl = {"name": decl, "edecl": decl} if hasattr(self, "full_decl") and self.full_decl: traverse(self.f2003, get_edecl, edecl) decls.append(edecl["edecl"]) del new_entity_decls attrs = self.attrspec if hasattr(self, "attrspec") else None if hasattr(self, "new_attrspec"): attrs = [] for attr in self.new_attr_specs: attrs.append(attr) del self.new_attr_specs if hasattr(self, "remove_attr"): newattrs = [] for attr in attrs: if any(attr.startswith(rattr) for rattr in self.remove_attr): pass else: newattrs.append(attr) attrs = newattrs del self.remove_attr s = self.tostr() if attrs: s += ", " + ", ".join(attrs) if decls: s += " :: " + ", ".join(decls) return s
def tokgen(self): from kgen_utils import traverse def get_edecl(node, bag, depth): from Fortran2003 import Entity_Decl if isinstance(node, Entity_Decl) and node.items[0].string == bag['name']: bag['edecl'] = node.tostr() return True decls = self.entity_decls if hasattr(self, 'new_entity_decls'): decls = [] for decl in self.new_entity_decls: edecl = {'name': decl, 'edecl': decl} if hasattr(self, 'full_decl') and self.full_decl: traverse(self.f2003, get_edecl, edecl) decls.append(edecl['edecl']) del new_entity_decls attrs = self.attrspec if hasattr(self, 'attrspec') else None if hasattr(self, 'new_attrspec'): attrs = [] for attr in self.new_attr_specs: attrs.append(attr) del self.new_attr_specs if hasattr(self, 'remove_attr'): newattrs = [] for attr in attrs: if any(attr.startswith(rattr) for rattr in self.remove_attr): pass else: newattrs.append(attr) attrs = newattrs del self.remove_attr s = self.tostr() if attrs: s += ', ' + ', '.join(attrs) if decls: s += ' :: ' + ', '.join(decls) return s
def preprocess(): from kgen_state import SrcFile if Config.check_mode: check_mode() sys.exit(0) else: if Config.mpi['enabled']: # get path of mpif.h mpifpath = '' if os.path.isabs(Config.mpi['header']): if os.path.exists(Config.mpi['header']): mpifpath = Config.mpi['header'] else: raise UserException('Can not find %s' % Config.mpi['header']) else: for p in Config.include['path']: # KGEN addition fp = os.path.join(p, Config.mpi['header']) if os.path.exists(fp): mpifpath = fp break # collect required information if mpifpath: try: reader = FortranFileReader( mpifpath, include_dirs=Config.include['path']) spec = Specification_Part(reader) bag = {} if Config.mpi['comm'] is None: bag['key'] = 'MPI_COMM_WORLD' bag[bag['key']] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if bag.has_key(bag['key']): Config.mpi['comm'] = bag[bag['key']][-1] else: raise UserException( 'Can not find MPI_COMM_WORLD in mpif.h') if Config.mpi['logical'] is None: bag['key'] = 'MPI_LOGICAL' bag[bag['key']] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if bag.has_key(bag['key']): Config.mpi['logical'] = bag[bag['key']][-1] else: raise UserException( 'Can not find MPI_LOGICAL in mpif.h') if Config.mpi['status_size'] is None: bag['key'] = 'MPI_STATUS_SIZE' bag[bag['key']] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if bag.has_key(bag['key']): Config.mpi['status_size'] = bag[bag['key']][-1] else: raise UserException( 'Can not find MPI_STATUS_SIZE in mpif.h') if Config.mpi['any_source'] is None: bag['key'] = 'MPI_ANY_SOURCE' bag[bag['key']] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if bag.has_key(bag['key']): Config.mpi['any_source'] = bag[bag['key']][-1] else: raise UserException( 'Can not find MPI_ANY_SOURCE in mpif.h') if Config.mpi['source'] is None: bag['key'] = 'MPI_SOURCE' bag[bag['key']] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if bag.has_key(bag['key']): Config.mpi['source'] = bag[bag['key']][-1] else: raise UserException( 'Can not find MPI_SOURCE in mpif.h') except Exception as e: raise UserException('Error occurred during reading %s.' % mpifpath) else: raise UserException( 'Can not find mpif.h. Please provide a path to the file') # parse imported source files through include.ini for path, import_type in Config.include['import'].iteritems(): if 'source' == import_type: State.imported['source'].append(SrcFile(path))
def locate_callsite(cs_tree): from statements import Comment from block_statements import executable_construct import re def get_next_non_comment(stmt): if not stmt: return if not hasattr(stmt, 'parent'): return started = False for s in stmt.parent.content: if s == stmt: if not isinstance(s, Comment): return s started = True elif started: if not isinstance(s, Comment): return s def get_names(node, bag, depth): from Fortran2003 import Name if isinstance(node, Name) and not node.string in bag: bag.append(node.string) # collect directives directs = [] for stmt, depth in walk(cs_tree): if isinstance(stmt, Comment): line = stmt.item.comment.strip() match = re.match(r'^[c!*]\$kgen\s+(.+)$', line, re.IGNORECASE) if match: dsplit = match.group(1).split(' ', 1) dname = dsplit[0].strip() if len(dsplit) > 1: clause = dsplit[1].strip() else: clause = None if dname.startswith('begin_'): sname = dname[6:] directs.append(sname) State.kernel['name'] = clause elif dname.startswith('end_'): ename = dname[4:] if directs[-1] == ename: directs.pop() if ename == 'callsite': pass else: raise UserException( 'WARNING: Not supported KGEN directive: %s' % ename) else: raise UserException('Directive name mismatch: %s, %s' % (dname_stack[-1], ename)) elif dname == 'callsite': next_fort_stmt = get_next_non_comment(stmt) if next_fort_stmt: State.kernel['name'] = clause State.callsite['stmts'].append(next_fort_stmt) else: raise UserException('WARNING: callsite is not found') else: if Config.callsite[ 'namepath'] and stmt.__class__ in executable_construct: names = [] traverse(stmt.f2003, get_names, names) for name in names: if match_namepath(Config.callsite['namepath'], pack_exnamepath(stmt, name), internal=False): State.kernel['name'] = name for _s, _d in walk(stmt): State.callsite['stmts'].append(_s) return elif len(directs) > 0 and directs[-1] == 'callsite': State.callsite['stmts'].append(stmt) if len(State.callsite['stmts']) == 0: raise UserException('Can not find callsite')
def update_state_info(parent): def get_nodes(node, bag, depth): from Fortran2003 import Name if isinstance( node, Name ) and node.string == bag['name'] and not node.parent in bag: anc = [node] while hasattr(node, 'parent'): anc.insert(0, node.parent) node = node.parent bag['lineage'].append(anc) if hasattr(parent, 'content'): for stmt in parent.content: if isinstance(stmt, TypeDeclarationStatement) and \ "parameter" not in stmt.attrspec and hasattr(stmt, 'geninfo') and \ any(len(v)>0 for v in stmt.geninfo.values()): for uname, req in KGGenType.get_state_in(stmt.geninfo): if KGGenType.has_uname_out(uname, stmt.geninfo): continue org = req.originator if org in State.callsite['stmts']: bag = {'name': uname.firstpartname(), 'lineage': []} traverse(org.f2003, get_nodes, bag) for lineage in bag['lineage']: copied = False for lidx, anc in enumerate(lineage): # get callname callname = None if anc.__class__ in [ Call_Stmt, Function_Reference ]: callname = anc.items[0].string elif anc.__class__ == Part_Ref: callname = anc.items[0].string elif anc.__class__ == Interface_Stmt: callname = anc.items[0].string # get caller and callee objects callobj = None subpobj = None if callname: for org_uname, org_req in org.unknowns.iteritems( ): if org_uname.firstpartname( ) == callname: if isinstance( org_req.res_stmts[0], SubProgramStatement): callobj = anc subpobj = org_req.res_stmts[0] break # get argument index argidx = -1 is_keyword = False if callobj and subpobj: if callobj.__class__ in [ Call_Stmt, Function_Reference ]: arglist = callobj.items[1] if arglist is None: pass elif isinstance( arglist, Actual_Arg_Spec): argobj = lineage[lidx + 1] kword = argobj.items[0].string argidx = subpobj.args.index(kword) elif isinstance( arglist, Actual_Arg_Spec_List): #if len(lineage)<(lidx+3): import pdb; pdb.set_trace() argobj = lineage[lidx + 2] argidx = arglist.items.index( argobj) if isinstance( argobj, Actual_Arg_Spec): kword = argobj.items[0].string argidx = subpobj.args.index( kword) else: argidx = 0 elif anc.__class__ == Part_Ref: arglist = callobj.items[1] if arglist is None: pass elif isinstance( arglist, Structure_Constructor_2): argobj = lineage[lidx + 1] kword = argobj.items[0].string argidx = subpobj.args.index(kword) elif isinstance( arglist, Section_Subscript_List): #if len(lineage)<(lidx+3): import pdb; pdb.set_trace() argobj = lineage[lidx + 2] argidx = arglist.items.index( argobj) if isinstance( argobj, Structure_Constructor_2): kword = argobj.items[0].string argidx = subpobj.args.index( kword) else: argidx = 0 elif anc.__class__ == Interface_Stmt: import pdb pdb.set_trace() # get intent if argidx >= 0: argname = subpobj.args[argidx] var = subpobj.a.variables[ subpobj.args[argidx]] if var.is_intent_out( ) or var.is_intent_inout(): req.gentype = KGGenType.STATE_OUT stmt.add_geninfo(uname, req) copied = True break if copied: break if hasattr(parent, 'parent'): update_state_info(parent.parent)
def locate_callsite(cs_tree): from statements import Comment from block_statements import executable_construct import re def get_next_non_comment(stmt): if not stmt: return if not hasattr(stmt, 'parent'): return started = False for s in stmt.parent.content: if s==stmt: if not isinstance(s, Comment): return s started = True elif started: if not isinstance(s, Comment): return s def get_names(node, bag, depth): from Fortran2003 import Name if isinstance(node, Name) and not node.string in bag: bag.append(node.string) # collect directives directs = [] for stmt, depth in walk(cs_tree): if isinstance(stmt, Comment): line = stmt.item.comment.strip() match = re.match(r'^[c!*]\$kgen\s+(.+)$', line, re.IGNORECASE) if match: dsplit = match.group(1).split(' ', 1) dname = dsplit[0].strip() if len(dsplit)>1: clause = dsplit[1].strip() else: clause = None if dname.startswith('begin_'): sname = dname[6:] directs.append(sname) State.kernel['name'] = clause elif dname.startswith('end_'): ename = dname[4:] if directs[-1]==ename: directs.pop() if ename=='callsite': pass else: raise UserException('WARNING: Not supported KGEN directive: %s'%ename) else: raise UserException('Directive name mismatch: %s, %s'%(dname_stack[-1], ename)) elif dname=='callsite': next_fort_stmt = get_next_non_comment(stmt) if next_fort_stmt: State.kernel['name'] = clause State.callsite['stmts'].append(next_fort_stmt) else: raise UserException('WARNING: callsite is not found') elif 'callsite' in directs: State.callsite['stmts'].append(stmt) elif 'callsite' in directs: State.callsite['stmts'].append(stmt) else: if Config.callsite['namepath'] and stmt.__class__ in executable_construct: names = [] traverse(stmt.f2003, get_names, names) for name in names: if match_namepath(Config.callsite['namepath'], pack_exnamepath(stmt, name), internal=False): State.kernel['name'] = name for _s, _d in walk(stmt): State.callsite['stmts'].append(_s) return elif len(directs)>0 and directs[-1]=='callsite': State.callsite['stmts'].append(stmt) if len(State.callsite['stmts'])==0: raise UserException('Can not find callsite')
def update_state_info(parent): def get_nodes(node, bag, depth): from Fortran2003 import Name if isinstance(node, Name) and node.string==bag['name'] and not node.parent in bag: anc = [node] while hasattr(node, 'parent'): anc.insert(0, node.parent) node = node.parent bag['lineage'].append(anc) if hasattr(parent, 'content'): for stmt in parent.content: if isinstance(stmt, TypeDeclarationStatement) and \ "parameter" not in stmt.attrspec and hasattr(stmt, 'geninfo') and \ any(len(v)>0 for v in stmt.geninfo.values()): for uname, req in KGGenType.get_state_in(stmt.geninfo): if KGGenType.has_uname_out(uname, stmt.geninfo): continue org = req.originator if org in State.callsite['stmts']: bag = {'name': uname.firstpartname(), 'lineage': [] } traverse(org.f2003, get_nodes, bag) for lineage in bag['lineage']: copied = False for lidx, anc in enumerate(lineage): # get callname callname = None if anc.__class__ in [ Call_Stmt, Function_Reference ]: callname = anc.items[0].string elif anc.__class__ == Part_Ref: callname = anc.items[0].string elif anc.__class__ == Interface_Stmt: callname = anc.items[0].string # get caller and callee objects callobj = None subpobj = None if callname: for org_uname, org_req in org.unknowns.iteritems(): if org_uname.firstpartname()==callname: if isinstance(org_req.res_stmts[0], SubProgramStatement): callobj = anc subpobj = org_req.res_stmts[0] break # get argument index argidx = -1 is_keyword = False if callobj and subpobj: if callobj.__class__ in [ Call_Stmt, Function_Reference ]: arglist = callobj.items[1] if arglist is None: pass elif isinstance(arglist, Actual_Arg_Spec): argobj = lineage[lidx+1] kword = argobj.items[0].string argidx = subpobj.args.index(kword) elif isinstance(arglist, Actual_Arg_Spec_List): #if len(lineage)<(lidx+3): import pdb; pdb.set_trace() argobj = lineage[lidx+2] argidx = arglist.items.index(argobj) if isinstance(argobj, Actual_Arg_Spec): kword = argobj.items[0].string argidx = subpobj.args.index(kword) else: argidx = 0 elif anc.__class__ == Part_Ref: arglist = callobj.items[1] if arglist is None: pass elif isinstance(arglist, Structure_Constructor_2): argobj = lineage[lidx+1] kword = argobj.items[0].string argidx = subpobj.args.index(kword) elif isinstance(arglist, Section_Subscript_List): #if len(lineage)<(lidx+3): import pdb; pdb.set_trace() argobj = lineage[lidx+2] argidx = arglist.items.index(argobj) if isinstance(argobj, Structure_Constructor_2): kword = argobj.items[0].string argidx = subpobj.args.index(kword) else: argidx = 0 elif anc.__class__ == Interface_Stmt: import pdb; pdb.set_trace() # get intent if argidx>=0: argname = subpobj.args[argidx] var = subpobj.a.variables[subpobj.args[argidx]] if var.is_intent_out() or var.is_intent_inout(): req.gentype = KGGenType.STATE_OUT stmt.add_geninfo(uname, req) copied = True break if copied: break if hasattr(parent, 'parent'): update_state_info(parent.parent)
def preprocess(): from kgen_state import SrcFile if Config.check_mode: check_mode() sys.exit(0) else: if Config.mpi['enabled']: # get path of mpif.h mpifpath = '' if os.path.isabs(Config.mpi['header']): if os.path.exists(Config.mpi['header']): mpifpath = Config.mpi['header'] else: raise UserException('Can not find %s'%Config.mpi['header']) else: for p in Config.include['path']: fp = os.path.join(p, Config.mpi['header']) if os.path.exists(fp): mpifpath = fp break if not mpifpath: for incpath, incdict in Config.include['file'].items(): for p in incdict['path']: fp = os.path.join(p, Config.mpi['header']) if os.path.exists(fp): mpifpath = fp break if mpifpath: break # collect required information # TODO: FortranFileReader should be replaced with FortranStringReader after preprocessing # TODO: include keyword should be handdled properly too. if mpifpath: try: reader = FortranFileReader(mpifpath, include_dirs = Config.include['path']) spec = Specification_Part(reader) bag = {} config_name_mapping = [ ('comm', 'MPI_COMM_WORLD'), ('logical', 'MPI_LOGICAL'), ('status_size', 'MPI_STATUS_SIZE'), ('any_source', 'MPI_ANY_SOURCE'), ('source', 'MPI_SOURCE'), ] for config_key, name in config_name_mapping: if not Config.mpi.has_key(config_key) or Config.mpi[config_key] is None: bag['key'] = name bag[name] = [] traverse(spec, get_MPI_PARAM, bag, subnode='content') if len(bag[name]) > 0: Config.mpi[config_key] = bag[name][-1] else: raise UserException('Can not find {name} in mpif.h'.format(name=name)) except UserException: raise # Reraise this exception rather than catching it below except Exception as e: raise UserException('Error occurred during reading %s.'%mpifpath) else: raise UserException('Can not find mpif.h. Please provide a path to the file') # parse imported source files through include.ini for path, import_type in Config.include['import'].iteritems(): if 'source'==import_type: State.imported['source'].append(SrcFile(path))