summaryrefslogtreecommitdiff
path: root/numpy/f2py/lib/base_classes.py
diff options
context:
space:
mode:
authorPearu Peterson <pearu.peterson@gmail.com>2006-07-04 12:12:47 +0000
committerPearu Peterson <pearu.peterson@gmail.com>2006-07-04 12:12:47 +0000
commita8672c2c5e1fe4ae0c51805aa1eed5d736a5eedf (patch)
treeb081bf1ae86d4b0f734157e2e7810c8fb43568b0 /numpy/f2py/lib/base_classes.py
parent17d8921d6d37745e01601fc19497ae2b4029b10c (diff)
downloadnumpy-a8672c2c5e1fe4ae0c51805aa1eed5d736a5eedf.tar.gz
Working on Fortran analyzer.
Diffstat (limited to 'numpy/f2py/lib/base_classes.py')
-rw-r--r--numpy/f2py/lib/base_classes.py177
1 files changed, 177 insertions, 0 deletions
diff --git a/numpy/f2py/lib/base_classes.py b/numpy/f2py/lib/base_classes.py
index cdae17f03..21aa63b8e 100644
--- a/numpy/f2py/lib/base_classes.py
+++ b/numpy/f2py/lib/base_classes.py
@@ -3,8 +3,155 @@ __all__ = ['Statement','BeginStatement','EndStatement']
import re
import sys
+import copy
from readfortran import Line
+from utils import split_comma, specs_split_comma
+class AttributeHolder:
+ # copied from symbolic.base module
+ """
+ Defines a object with predefined attributes. Only those attributes
+ are allowed that are specified as keyword arguments of a constructor.
+ When an argument is callable then the corresponding attribute will
+ be read-only and set by the value the callable object returns.
+ """
+ def __init__(self, **kws):
+ self._attributes = {}
+ self._readonly = []
+ for k,v in kws.items():
+ self._attributes[k] = v
+ if callable(v):
+ self._readonly.append(k)
+ return
+
+ def __getattr__(self, name):
+ if name not in self._attributes:
+ raise AttributeError,'%s instance has no attribute %r, '\
+ 'expected attributes: %s' \
+ % (self.__class__.__name__,name,
+ ','.join(self._attributes.keys()))
+ value = self._attributes[name]
+ if callable(value):
+ value = value()
+ self._attributes[name] = value
+ return value
+
+ def __setattr__(self, name, value):
+ if name in ['_attributes','_readonly']:
+ self.__dict__[name] = value
+ return
+ if name in self._readonly:
+ raise AttributeError,'%s instance attribute %r is readonly' \
+ % (self.__class__.__name__, name)
+ if name not in self._attributes:
+ raise AttributeError,'%s instance has no attribute %r, '\
+ 'expected attributes: %s' \
+ % (self.__class__.__name__,name,','.join(self._attributes.keys()))
+ self._attributes[name] = value
+
+ def __repr__(self):
+ l = []
+ for k in self._attributes.keys():
+ v = getattr(self,k)
+ l.append('%s=%r' % (k,v))
+ return '%s(%s)' % (self.__class__.__name__,', '.join(l))
+
+ def todict(self):
+ d = {}
+ for k in self._attributes.keys():
+ v = getattr(self, k)
+ d[k] = v
+ return d
+
+def get_base_classes(cls):
+ bases = ()
+ for c in cls.__bases__:
+ bases += get_base_classes(c)
+ return bases + cls.__bases__ + (cls,)
+
+class Variable:
+ """
+ Variable instance has attributes:
+ name
+ typedecl
+ dimension
+ attributes
+ intent
+ parent - Statement instances defining the variable
+ """
+ def __init__(self, parent, name):
+ self.parent = parent
+ self.name = name
+ self.typedecl = None
+ self.dimension = None
+ self.attributes = []
+ self.intent = None
+ self.bind = []
+ self.check = []
+ return
+
+ def set_type(self, typedecl):
+ if self.typedecl is not None:
+ if not self.typedecl==typedecl:
+ message = 'Warning: variable %r already has type %s' \
+ % (self.name, self.typedecl.tostr())
+ message += '.. resetting to %s' % (typedecl.tostr())
+ self.parent.show_message(message)
+ self.typedecl = typedecl
+ return
+
+ def update(self, attrs):
+ attributes = self.attributes
+ for attr in attrs:
+ lattr = attr.lower()
+ uattr = attr.upper()
+ if lattr.startswith('dimension'):
+ assert self.dimension is None, `self.dimension,attr`
+ l = attr[9:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.dimension = split_comma(l[1:-1].strip(), self.parent.item)
+ continue
+ if lattr.startswith('intent'):
+ l = attr[6:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.intent = intent = []
+ for i in split_comma(l[1:-1].strip(), self.parent.item):
+ if i not in intent:
+ intent.append(i)
+ continue
+ if lattr.startswith('bind'):
+ l = attr[4:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.bind = specs_split_comma(l[1:-1].strip(), self.parent.item)
+ continue
+ if lattr.startswith('check'):
+ l = attr[5:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.check.extend(split_comma(l[1:-1].strip()), self.parent.item)
+ continue
+ if uattr not in attributes:
+ attributes.append(uattr)
+ return
+
+ def __str__(self):
+ s = ''
+ if self.typedecl is not None:
+ s += self.typedecl.tostr() + ' '
+ a = self.attributes[:]
+ if self.dimension is not None:
+ a.append('DIMENSION(%s)' % (', '.join(self.dimension)))
+ if self.intent is not None:
+ a.append('INTENT(%s)' % (', '.join(self.intent)))
+ if self.bind:
+ a.append('BIND(%s)' % (', '.join(self.bind)))
+ if self.check:
+ a.append('CHECK(%s)' % (', '.join(self.check)))
+ if a:
+ s += ', '.join(a) + ' :: '
+ return s + self.name
+
+class ProgramBlock:
+ pass
class Statement:
"""
@@ -18,6 +165,14 @@ class Statement:
def __init__(self, parent, item):
self.parent = parent
self.reader = parent.reader
+ self.top = getattr(parent,'top',None)
+ if isinstance(parent, ProgramBlock):
+ self.programblock = parent
+ elif isinstance(self, ProgramBlock):
+ self.programblock = self
+ elif hasattr(parent,'programblock'):
+ self.programblock = parent.programblock
+
self.item = item
# when a statement instance is constructed by error, set isvalid to False
@@ -25,8 +180,19 @@ class Statement:
# when a statement should be ignored, set ignore to True
self.ignore = False
+ # attribute a will hold analyze information.
+ a_dict = {}
+ for cls in get_base_classes(self.__class__):
+ if hasattr(cls,'a'):
+ a_dict.update(copy.deepcopy(cls.a.todict()))
+ self.a = AttributeHolder(**a_dict)
+ if hasattr(self.__class__,'a'):
+ assert self.a is not self.__class__.a
+
self.process_item()
+ return
+
def get_indent_tab(self,colon=None,deindent=False):
if self.reader.isfix:
tab = ' '*6
@@ -60,6 +226,10 @@ class Statement:
sys.stderr.flush()
return
+ def analyze(self):
+ self.show_message('nothing analyzed in %s' % (self.__class__.__name__))
+ return
+
class BeginStatement(Statement):
""" <blocktype> <name>
@@ -237,6 +407,10 @@ class BeginStatement(Statement):
#sys.exit()
return
+ def analyze(self):
+ for stmt in self.content:
+ stmt.analyze()
+ return
class EndStatement(Statement):
"""
@@ -274,6 +448,9 @@ class EndStatement(Statement):
self.isvalid = False
self.name = self.parent.name
+ def analyze(self):
+ return
+
def __str__(self):
return self.get_indent_tab()[:-2] + 'END %s %s'\
% (self.blocktype.upper(),self.name or '')