summaryrefslogtreecommitdiff
path: root/grc/core/blocks/block.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core/blocks/block.py')
-rw-r--r--grc/core/blocks/block.py98
1 files changed, 96 insertions, 2 deletions
diff --git a/grc/core/blocks/block.py b/grc/core/blocks/block.py
index c3502397ec..4df3ec9663 100644
--- a/grc/core/blocks/block.py
+++ b/grc/core/blocks/block.py
@@ -21,9 +21,11 @@ from __future__ import absolute_import
import collections
import itertools
+import copy
import six
from six.moves import range
+import re
from ._templates import MakoTemplates
from ._flags import Flags
@@ -31,7 +33,6 @@ from ._flags import Flags
from ..base import Element
from ..utils.descriptors import lazy_property
-
def _get_elem(iterable, key):
items = list(iterable)
for item in items:
@@ -49,6 +50,7 @@ class Block(Element):
key = ''
label = ''
category = ''
+ vtype = '' # This is only used for variables when we want C++ output
flags = Flags('')
documentation = {'': ''}
@@ -83,6 +85,7 @@ class Block(Element):
self.active_sinks = [] # on rewrite
self.states = {'state': True}
+ self.orig_cpp_templates = self.cpp_templates # The original template, in case we have to edit it when transpiling to C++
# region Rewrite_and_Validation
def rewrite(self):
@@ -136,6 +139,7 @@ class Block(Element):
Element.validate(self)
self._run_asserts()
self._validate_generate_mode_compat()
+ self._validate_output_language_compat()
self._validate_var_value()
def _run_asserts(self):
@@ -161,6 +165,13 @@ class Block(Element):
check_generate_mode('QT GUI', Flags.NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
+ def _validate_output_language_compat(self):
+ """check if this block supports the selected output language"""
+ current_output_language = self.parent.get_option('output_language')
+
+ if current_output_language == 'cpp' and 'has_cpp' not in self.flags:
+ self.add_error_message("This block does not support C++ output.")
+
def _validate_var_value(self):
"""or variables check the value (only if var_value is used)"""
if self.is_variable and self.value != 'value':
@@ -227,6 +238,9 @@ class Block(Element):
def get_var_make(self):
return self.templates.render('var_make')
+ def get_cpp_var_make(self):
+ return self.cpp_templates.render('var_make')
+
def get_var_value(self):
return self.templates.render('var_value')
@@ -241,8 +255,88 @@ class Block(Element):
if 'self.' in callback:
return callback
return 'self.{}.{}'.format(self.name, callback)
+
return [make_callback(c) for c in self.templates.render('callbacks')]
+ def get_cpp_callbacks(self):
+ """
+ Get a list of C++ function callbacks for this block.
+
+ Returns:
+ a list of strings
+ """
+ def make_callback(callback):
+ if 'this->' in callback:
+ return callback
+ return 'this->{}->{}'.format(self.name, callback)
+
+ return [make_callback(c) for c in self.cpp_templates.render('callbacks')]
+
+ def decide_type(self):
+ """
+ Evaluate the value of the variable block and decide its type.
+
+ Returns:
+ None
+ """
+ value = self.params['value'].value
+ self.cpp_templates = copy.copy(self.orig_cpp_templates)
+
+ def get_type(element):
+ try:
+ evaluated = ast.literal_eval(element)
+
+ except ValueError or SyntaxError:
+ if re.match(r'^(numpy|np|scipy|sp)\.pi$', value):
+ return 'pi'
+ else:
+ return 'std::string'
+
+ else:
+ _vtype = type(evaluated)
+ if _vtype in [int, float, bool, list]:
+ if _vtype == (int or long):
+ return 'int'
+
+ if _vtype == float:
+ return 'double'
+
+ if _vtype == bool:
+ return 'bool'
+
+ if _vtype == list:
+ try:
+ first_element_type = type(evaluated[0])
+ if first_element_type != str:
+ list_type = get_type(str(evaluated[0]))
+ else:
+ list_type = get_type(evaluated[0])
+
+ except IndexError: # empty list
+ return 'std::vector<std::string>'
+
+ else:
+ return 'std::vector<' + list_type + '>'
+
+ else:
+ return 'std::string'
+
+ self.vtype = get_type(value)
+ if self.vtype == 'bool':
+ self.cpp_templates['var_make'] = self.cpp_templates['var_make'].replace('${value}', (value[0].lower() + value[1:]))
+
+ elif self.vtype == 'pi':
+ self.vtype = 'double'
+ self.cpp_templates['var_make'] = self.cpp_templates['var_make'].replace('${value}', 'boost::math::constants::pi<double>()')
+ self.cpp_templates['includes'].append('#include <boost/math/constants/constants.hpp>')
+
+ elif 'std::vector' in self.vtype:
+ self.cpp_templates['includes'].append('#include <vector>')
+ self.cpp_templates['var_make'] = self.cpp_templates['var_make'].replace('${value}', '{' + value[1:-1] + '}')
+
+ if 'string' in self.vtype:
+ self.cpp_templates['includes'].append('#include <string>')
+
def is_virtual_sink(self):
return self.key == 'virtual_sink'
@@ -261,7 +355,7 @@ class Block(Element):
Bypass the block
Returns:
- True if block chagnes state
+ True if block changes state
"""
if self.state != 'bypassed' and self.can_bypass():
self.state = 'bypassed'