[Top][All Lists]
[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
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8863 - in grc/trunk: notes src/grc_gnuradio,
jblum <=