# Copyright, 1999, Regents of the University of California
# Please see file Legal.htm
import types, string
class FortranType:
"Description of a Fortran type."
def __init__ (self, name, kind=None):
assert type(name) == types.StringType
assert kind is None or type(kind) == types.StringType
self.name = name
self.kind = kind
def __repr__ (self):
if self.name == 'character' and self.kind:
s = 'character*(' + self.kind + ')'
else:
s = self.name
if self.kind:
s = s + '(' + self.kind + ')'
return s
class FortranAttributes:
"Attributes a Fortran entity can have"
def __init__(self, type, intent, allocatable):
assert is_FortranType(type)
assert intent == 'in' or intent == 'out' or intent == 'inout' \
or intent == 'temporary' or intent == 'valued'
self.intent = intent
self.type = type
self.allocatable = allocatable
def __repr__(self):
s = repr(self.type) + ", intent = " + self.intent
if self.allocatable: s = s + ", allocatable"
return s
class FortranProcedure:
"Interface info to a Fortran subroutine or function"
def __init__(self, head, declarations):
self.head = head
self.dict = {}
self.dict[self.routine_name()] = None
for a in self.arguments():
self.dict[a] = None
for d in declarations:
self.dict[d.name] = d
for name in self.dict.keys():
if name == self.routine_name() and not self.is_function():
if not (self.dict[name] is None):
print name + " is declared in the body but it is a subroutine."
raise SystemExit, 1
self.dict[name] = void_declaration(name)
else:
if self.dict[name] is None:
print name + " is not given a type in routine " + self.routine_name()
raise SystemExit, 1
if self.is_function():
self.dict[self.routine_name()].set_intent("out")
def __repr__(self):
s = repr(self.head) + "\n"
for x in self.declarations():
s = s + " " + repr(x) + "\n"
return s
def routine_name (self):
"name of the routine"
return self.head[1]
def arguments (self):
"names of the arguments"
return self.head[2]
def python_inputs(self):
"list of arguments whose intent is in or inout"
result = []
for x in self.arguments():
k = self.dict[x].intent
if k == 'in' or k == 'inout':
result.append(x)
return result
def valued (self):
"list of arguments whose intent is valued"
result = []
for x in self.arguments():
k = self.dict[x].intent
if k == 'valued':
result.append(x)
return result
def temporaries(self):
"list of arguments whose intent is temporary"
result = []
for x in self.arguments():
k = self.dict[x].intent
if k == "temporary":
result.append(x)
return result
def in_and_outs(self):
"list of arguments whose intent is inout"
result = []
for x in self.arguments():
k = self.dict[x].intent
if k == "inout":
result.append(x)
return result
def python_outputs(self):
"""list of arguments of type out, preceded by name of function
if it is a function"""
# note that inouts are not outputs
result = []
if self.is_function():
result.append(self.routine_name())
for x in self.arguments():
k = self.dict[x].intent
if k == 'out':
result.append(x)
return result
def routine_type (self):
"subroutine or function?"
return self.head[0]
def return_type (self):
"type returned by this function"
if self.is_function():
return self.declaration(self.routine_name()).type
else:
return FortranType("none")
def is_function (self):
"is this a function?"
return self.routine_type() == 'function'
def head_comments (self, indent=0):
"Comments connected with the procedure itself."
cs = []
sep = ' '*indent
for c in self.head[3]:
cc = c
if cc[0:1] == '!': cc = cc[1:]
if cc[0:1] == ' ': cc = cc[1:]
cs.append(sep + cc)
return sep + string.join(cs, '\n')
def declaration(self, name):
"the declaration object for the entity with the given name"
return self.dict[name]
def declarations(self):
"The list of declarations"
result = []
if self.is_function():
result.append(self.declaration(self.routine_name()))
for s in self.arguments():
result.append(self.declaration(s))
return result
def make_procedure(self):
routine_type = 'procedure'
routine_name = self.head[1]
argument_name = routine_name + 'arg'
arguments = [argument_name] + self.head[2]
declaration = FortranDeclaration (argument_name,[])
declaration.set_intent ("out")
declaration.set_type (self.dict[routine_name].type)
self.dict[argument_name] = declaration
self.head = routine_type, self.head[1], arguments, self.head[3]
type = FortranType ("none")
self.dict[routine_name].set_type (type)
def add_argument(self, name, type, intent, preceding):
arguments = self.head[2]
i = arguments.index(preceding)
arguments = arguments[:i+1] + [name] + arguments[i+1:]
self.head = self.head[0], self.head[1], arguments, self.head[3]
declaration = FortranDeclaration (name,[])
declaration.set_intent (intent)
declaration.set_type (type)
self.dict[name] = declaration
unknown_type = FortranType('unknown-type')
class FortranDeclaration:
"Declaration of a variable"
def __init__(self, name, dimlist):
assert type(name) == types.StringType
assert type(dimlist) == types.ListType
self.name = name
self.dimlist = dimlist
self.type = unknown_type
self.intent = 'unknown-intent'
self.allocatable = 0
self.comment = ''
def set_info(self, attributes):
assert is_FortranAttributes(attributes)
self.set_type(attributes.type)
self.set_intent(attributes.intent)
self.set_allocatable(attributes.allocatable)
def set_comment(self, comment):
assert type(comment) == types.StringType
self.comment = comment
def set_type(self, type):
self.type = type
def set_intent (self, intent):
self.intent = intent
def set_allocatable (self, allocatable):
self.allocatable = allocatable
def dimstr(self):
"String repr of dimlist "
if self.dimlist:
s = string.join (self.dimlist, ', ')
else:
s = ''
return s
def rank (self):
"Number of dimensions."
return len(self.dimlist)
def dimension (self, i):
"i'th dimension, 0 based."
assert i <= self.rank()
assert i >= 0
return self.dimlist[i]
def __repr__(self):
s = repr(self.type) + ', intent(' + self.intent + '):: ' + self.name
if self.dimlist:
s = s + ' (' + self.dimstr() + ')'
if self.allocatable:
s = s + ' allocatable'
return s
def void_declaration (name):
d = FortranDeclaration (name, [])
d.set_intent("out")
d.set_type(FortranType("none"))
return d
def is_FortranAttributes (s):
return type(s) == types.InstanceType and s.__class__ == FortranAttributes
def is_FortranProcedure (s):
return type(s) == types.InstanceType and s.__class__ == FortranProcedure
def is_FortranType (s):
return type(s) == types.InstanceType and s.__class__ == FortranType
def is_FortranDeclaration (s):
return type(s) == types.InstanceType and s.__class__ == FortranDeclaration
|