commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r8863 - in grc/trunk: notes src/grc_gnuradio


From: jblum
Subject: [Commit-gnuradio] r8863 - in grc/trunk: notes src/grc_gnuradio
Date: Thu, 10 Jul 2008 18:33:32 -0600 (MDT)

Author: jblum
Date: 2008-07-10 18:33:32 -0600 (Thu, 10 Jul 2008)
New Revision: 8863

Added:
   grc/trunk/src/grc_gnuradio/expr_utils.py
Modified:
   grc/trunk/notes/todo.txt
   grc/trunk/src/grc_gnuradio/FlowGraph.py
   grc/trunk/src/grc_gnuradio/Param.py
Log:
variable dependency resolution

Modified: grc/trunk/notes/todo.txt
===================================================================
--- grc/trunk/notes/todo.txt    2008-07-11 00:07:49 UTC (rev 8862)
+++ grc/trunk/notes/todo.txt    2008-07-11 00:33:32 UTC (rev 8863)
@@ -14,6 +14,7 @@
 -block tree class
 -dtd for external blocks
 -hotkeys in action descriptions
+-switch to generation of top_block and hier_block2 classes
 
 ############   Suggestions:    ####################
 -simple usrp

Modified: grc/trunk/src/grc_gnuradio/FlowGraph.py
===================================================================
--- grc/trunk/src/grc_gnuradio/FlowGraph.py     2008-07-11 00:07:49 UTC (rev 
8862)
+++ grc/trunk/src/grc_gnuradio/FlowGraph.py     2008-07-11 00:33:32 UTC (rev 
8863)
@@ -20,12 +20,13 @@
 #Primative flow graph.
 address@hidden Josh Blum
 
+import expr_utils
 from grc.elements.FlowGraph import FlowGraph as _FlowGraph
 from Block import Block
 from Connection import Connection
 
 class FlowGraph(_FlowGraph):
-       
+
        def get_imports(self):
                """!
                Get a set of all import statments in this flow graph namespace.
@@ -34,16 +35,23 @@
                imports = sum([block.get_imports() for block in 
self.get_blocks()], [])
                imports = sorted(set(imports))
                return imports
-       
+
        def get_variables(self):
                """!
                Get a list of all variables in this flow graph namespace.
                @return a sorted list of variable blocks
                """
                variables = filter(lambda b: b.get_key() in ('variable', 
'variable_slider', 'variable_chooser'), self.get_blocks())
-               variables = sorted(variables, lambda x, y: cmp(x.get_id(), 
y.get_id()))
-               return variables        
-       
+               #map var id to variable block
+               id2var = dict([(var.get_id(), var) for var in variables])
+               #map var id to variable code
+               id2expr = dict([(var.get_id(), var.get_make().split('\n')[0]) 
for var in variables])
+               #sort according to dependency
+               sorted_ids = expr_utils.sort_variables(id2expr)
+               #create list of sorted variable blocks
+               variables = [id2var[id] for id in sorted_ids]
+               return variables
+
        def evaluate(self, expr):
                """!
                Evaluate the expression.
@@ -54,27 +62,25 @@
                if self.is_flagged():
                        self.deflag()
                        #reload namespace
-                       n_imp = dict()
-                       n_var = dict()
+                       n = dict()
                        #load imports
                        for imp in self.get_imports():
-                               try: exec imp in n_imp
+                               try: exec imp in n
                                except: pass
                        #load variables
                        for variable in self.get_variables():
-                               try: 
+                               try:
                                        if variable.get_key() == 
'variable_chooser':
                                                choices = 
variable.get_param('choices').to_code()
                                                value_index = 
variable.get_param('value_index').to_code()
-                                               e = eval("%s[%s]"%(choices, 
value_index), n_imp, n_imp)                                         
+                                               e = eval("%s[%s]"%(choices, 
value_index), n, n)
                                        else:
-                                               e = 
eval(variable.get_param('value').to_code(), n_imp, n_imp)
-                                       n_var[variable.get_id()] = e
+                                               e = 
eval(variable.get_param('value').to_code(), n, n)
+                                       n[variable.get_id()] = e
                                except: pass
-                       #merge variable and import namespace
-                       n_imp.update(n_var)
-                       self.n = n_imp
+                       #make namespace public
+                       self.n = n
                #evaluate
                e = eval(expr, self.n, self.n)
                return e
-               
+

Modified: grc/trunk/src/grc_gnuradio/Param.py
===================================================================
--- grc/trunk/src/grc_gnuradio/Param.py 2008-07-11 00:07:49 UTC (rev 8862)
+++ grc/trunk/src/grc_gnuradio/Param.py 2008-07-11 00:33:32 UTC (rev 8863)
@@ -32,7 +32,6 @@
                'hex', 'string',
                'file_open', 'file_save',
                'id',
-               'source_pad_key', 'sink_pad_key',
                'grid_pos', 'import',
        ]
 
@@ -54,8 +53,13 @@
                                return v
                t = self.get_type()
                v = self.get_value()
-               if self.is_enum():
-                       return self.get_value()
+               #########################
+               # Enum Type
+               #########################
+               if self.is_enum(): return self.get_value()
+               #########################
+               # Numeric Types
+               #########################
                elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 
'real_vector', 'int_vector', 'hex'):
                        #raise exception if python cannot evaluate this value
                        try: e = self.get_parent().get_parent().evaluate(v)
@@ -63,8 +67,7 @@
                                self._add_error_message('Value "%s" cannot be 
evaluated.'%v)
                                raise Exception
                        #raise an exception if the data is invalid
-                       if t == 'raw':
-                               return e
+                       if t == 'raw': return e
                        elif t == 'complex':
                                try: assert(isinstance(e, (complex, float, int, 
long)))
                                except AssertionError:
@@ -119,21 +122,16 @@
                        elif t == 'hex':
                                return hex(e)
                        else: raise TypeError, 'Type "%s" not handled'%t
-               elif t == 'string':
+               #########################
+               # String Types
+               #########################
+               elif t in ('string', 'file_open', 'file_save'):
+                       #do not check if file/directory exists, that is a 
runtime issue
                        e = eval_string(v)
                        return str(e)
-               elif t == 'file_open':
-                       e = eval_string(v)
-                       e = str(e)
-                       assert(os.path.isfile(e))
-                       return e
-               elif t == 'file_save':
-                       e = eval_string(v)
-                       e = str(e)
-                       assert(os.path.exists(os.path.dirname(e)))
-                       assert(not os.path.isdir(e))
-                       assert(os.path.basename(e))
-                       return e
+               #########################
+               # Unique ID Type
+               #########################
                elif t == 'id':
                        #can python use this as a variable?
                        try:
@@ -150,32 +148,9 @@
                                self._add_error_message('ID "%s" is not 
unique.'%v)
                                raise Exception
                        return v
-               elif t == 'source_pad_key':
-                       #should be an integer
-                       try: e = int(v)
-                       except:
-                               self._add_error_message('Source Pad Key "%s" is 
not an integer.'%v)
-                               raise Exception
-                       params = filter(lambda p: p.is_valid(), 
self.get_all_params('source_pad_key'))
-                       keys = [int(param.get_value()) for param in params]
-                       try: assert(len(keys) == len(set(keys)))
-                       except AssertionError:
-                               self._add_error_message('Source Pad Key "%s" is 
not unique.'%v)
-                               raise Exception
-                       return e
-               elif t == 'sink_pad_key':
-                       #should be an integer
-                       try: e = int(v)
-                       except:
-                               self._add_error_message('Sink Pad Key "%s" is 
not an integer.'%v)
-                               raise Exception
-                       params = filter(lambda p: p.is_valid(), 
self.get_all_params('sink_pad_key'))
-                       keys = [int(param.get_value()) for param in params]
-                       try: assert(len(keys) == len(set(keys)))
-                       except AssertionError:
-                               self._add_error_message('Sink Pad Key "%s" is 
not unique.'%v)
-                               raise Exception
-                       return e
+               #########################
+               # Grid Position Type
+               #########################
                elif t == 'grid_pos':
                        self._hostage_cells = list()
                        if not v: return '' #allow for empty grid pos
@@ -209,6 +184,9 @@
                                                
self._add_error_message('Another graphical element is using cell 
"%s".'%str(cell))
                                                raise Exception
                        return e
+               #########################
+               # Import Type
+               #########################
                elif t == 'import':
                        n = dict() #new namespace
                        try: exec v in n
@@ -219,6 +197,7 @@
                                self._add_error_message('Bad import syntax: 
"%s".'%v)
                                raise Exception
                        return filter(lambda k: str(k) != '__builtins__', 
n.keys())
+               #########################
                else: raise TypeError, 'Type "%s" not handled'%t
 
        def to_code(self):

Added: grc/trunk/src/grc_gnuradio/expr_utils.py
===================================================================
--- grc/trunk/src/grc_gnuradio/expr_utils.py                            (rev 0)
+++ grc/trunk/src/grc_gnuradio/expr_utils.py    2008-07-11 00:33:32 UTC (rev 
8863)
@@ -0,0 +1,77 @@
+"""
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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.
+
+GNU Radio Companion 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
+"""
address@hidden grc_gnuradio.expr_utils
+#Utility functions to comprehend variable expressions.
address@hidden Josh Blum
+
+import string
+VAR_CHARS = string.letters + string.digits + '_'
+
+def expr_split(expr):
+       """!
+       Split up an expression by non alphanumeric characters, including 
underscore.
+       @param expr an expression string
+       @return a list of string tokens that form expr
+       """
+       toks = list()
+       tok = ''
+       for char in expr:
+               if char in VAR_CHARS:
+                       tok += char
+               else:
+                       toks.append(tok)
+                       toks.append(char)
+                       tok = ''
+       toks.append(tok)
+       return filter(lambda t: t, toks)
+
+def get_variable_dependencies(expr, vars):
+       """!
+       Return a set of variables used in this expression.
+       @param expr an expression string
+       @param vars a list of variable names
+       @return a subset of vars used in the expression
+       """
+       expr_toks = expr_split(expr)
+       return set(filter(lambda v: v in expr_toks, vars))
+
+def sort_variables(exprs):
+       """!
+       Get a list of variables in order of dependencies.
+       @param exprs a mapping of variable name to expression
+       @return a list of variable names
+       @throws AssertionError circular dependencies
+       """
+       vars = exprs.keys()
+       #get dependencies for each expression
+       vars_deps = dict([(var, get_variable_dependencies(expr, vars)) for var, 
expr in exprs.iteritems()])
+       sorted_vars = list()
+       #determine dependency order
+       while vars_deps:
+               #get a list of vars with no dependencies
+               indep_vars = set(filter(lambda v: not vars_deps[v], 
vars_deps.keys()))
+               assert indep_vars
+               #remove inpep vars from dict
+               for var in indep_vars: vars_deps.pop(var)
+               #add the indep vars to the end of the list
+               sorted_vars.extend(sorted(indep_vars))
+               #remove deps from other vars involving indep_vars
+               for var in vars_deps.keys(): vars_deps[var] -= indep_vars
+       return sorted_vars
+





reply via email to

[Prev in Thread] Current Thread [Next in Thread]