def for_transformer(node, resources): _validate_restrictions(node) parent_block = resources.get_current_block() var_name = utils.get_variable_name_from_node(node.iter) if resources.has_variable(var_name): collection_value = resources.get_variable_py_value(var_name) if not isinstance(collection_value, ArrayType): raise TranslateError(_errormessages.scalar_iterable_collection) collection = resources.get_variable_rtseq_name(var_name) iterator = node.target.id for_statement = rtseqapi.add_foreach_loop(parent_block, iterator, collection) # add the iterator as local variable, so that attribute_transformer returns the actual rtseq name of # the iterator resources.add_variable(iterator, 0, iterator) resources.add_variable(iterator + ".value", 0, iterator) elif utils.generic_ast_node_transform(node.iter, resources).startswith("range("): if len(node.iter.args) > 1: raise TranslateError(_errormessages.invalid_range_call) max_range = utils.generic_ast_node_transform(node.iter.args[0], resources) variable = node.target.id for_statement = rtseqapi.add_for_loop(parent_block, variable, max_range) else: raise TranslateError(_errormessages.invalid_iterable_collection) for statement in node.body: resources.set_current_block(for_statement.Body) utils.generic_ast_node_transform(statement, resources) resources.set_current_block(parent_block)
def return_transformer(node, resources): _validate_restrictions(node) rtseq = resources.get_rtseq() expression = utils.generic_ast_node_transform(node.value, resources) stripped_expression = expression[:expression.find("[")] if expression.find( "[") != -1 else expression if isinstance(node.value, (ast.Name, ast.Attribute, ast.Subscript)): src_var_name = utils.get_variable_name_from_node(node.value) if resources.has_variable( str(src_var_name )) and not resources.has_channel_ref(stripped_expression): rt_expression = expression return_default_value = resources.get_variable_py_value( src_var_name) # In case of "return var[0]" the default value is saved as a list, so make sure to not return list type # because those cannot be return variables. # The len check is there to not get index error in case of empty lists -> for that I don't know yet # what the solution is, so I will leave it like this (Arnold) if isinstance(return_default_value, ArrayType): if len(return_default_value.value): return_default_value = return_default_value[0] else: raise TranslateError(_errormessages.invalid_return_value) elif isinstance(node.value, (ast.Num, ast.Call)): return_default_value = utils.get_value_from_node(node.value, resources) if isinstance(return_default_value, ArrayType): raise TranslateError(_errormessages.invalid_return_type) rt_expression = expression else: raise TranslateError(_errormessages.invalid_return_value) var_name = rtseqapi.add_return_variable(rtseq, '__ret_var__', return_default_value) rtseqapi.add_assignment(resources.get_current_block(), var_name, rt_expression) return "return " + str(expression)
def _transform(self): from niveristand._decorators import rt_seq_mode_id real_obj = getattr(self._top_level_func, rt_seq_mode_id, None) if real_obj is None: raise TranslateError(_errormessages.invalid_top_level_func) src = inspect.getsource(real_obj) top_node = ast.parse(src) try: func_node = top_node.body[0] except TypeError: func_node = None if func_node is None or not isinstance(func_node, ast.FunctionDef): raise TranslateError(_errormessages.invalid_top_level_func) self._rtseq = rtseqapi.create_real_time_sequence() transform_resources = Resources(self._rtseq, str(self)) if self._rtseqpkg is not None: transform_resources.set_dependency_pkg(self._rtseqpkg) utils.generic_ast_node_transform(func_node, transform_resources) self._rtseqpkg = transform_resources.get_dependency_pkg() self._rtseqpkg.append(inspect.getmodule(real_obj)) self._update_parameters(transform_resources.get_parameters()) self._update_channel_refs(transform_resources.get_all_channel_refs()) self.save() rtsequtils.compile_rtseq(self._rtseq)
def _validate_restrictions(node): if not isinstance(node.args[0], (ast.UnaryOp, ast.Num)): raise TranslateError( _errormessages.invalid_error_code_for_generate_error) if not isinstance(node.args[1], ast.Str): raise TranslateError(_errormessages.invalid_message_for_generate_error) if not isinstance(node.args[2], ast.Attribute): raise TranslateError(_errormessages.invalid_action_for_generate_error)
def _validate_restrictions(node): if node.handlers or node.orelse: raise TranslateError(_errormessages.invalid_try_except_orelse) if validations.check_if_any_in_block(ast.Return, node.body) or\ validations.check_if_any_in_block(ast.Return, node.finalbody): raise TranslateError( _errormessages.return_not_supported_in_try_finally) validations.raise_if_try_in_node_body(node.body)
def _validate_restrictions(node): if not isinstance(node.args[0], ast.UnaryOp) and not utils.is_node_ast_num( node.args[0]): raise TranslateError( _errormessages.invalid_error_code_for_generate_error) if not utils.is_node_ast_str(node.args[1]): raise TranslateError(_errormessages.invalid_message_for_generate_error) if not isinstance(node.args[2], ast.Attribute): raise TranslateError(_errormessages.invalid_action_for_generate_error)
def assign_transformer(node, resources): node_value = None initial_channel_ref_declaration = False lhs = node.targets[0] rtseq_var_name = utils.generic_ast_node_transform(lhs, resources) # the left hand side can only be a variable name or a name with an attribute (var.value) if isinstance(lhs, ast.Name): variable_name = utils.get_variable_name_from_node(lhs) # if the variable already exists this kind of assignment is invalid, use var.value instead if resources.has_variable(variable_name): raise TranslateError(_errormessages.variable_reassignment) elif isinstance(lhs, ast.Attribute): # in case of var[0].value get rid of the [0] part and search in the dictionary for var stripped_rtseq_var_name = rtseq_var_name[:rtseq_var_name.find("[")] if rtseq_var_name.find("[") != -1 \ else rtseq_var_name variable_name = resources.get_variable_py_name(stripped_rtseq_var_name) else: raise TranslateError(_errormessages.variable_reassignment) rtseq = resources.get_rtseq() block = resources.get_current_block() if not resources.has_variable(variable_name): # new local variable node_value = utils.get_value_from_node(node.value, resources) if isinstance( node_value, (_datatypes.ChannelReference, _datatypes.VectorChannelReference)): initial_channel_ref_declaration = True channel_name = utils.get_channel_name(node.value.args[0]) rtseq_var_name = rtseqapi.to_channel_ref_name(variable_name) resources.add_channel_ref( variable_name, channel_name, rtseq_var_name, isinstance(node_value, _datatypes.ArrayType)) elif isinstance(node_value, _datatypes.DataType): rtseq_var_name = rtseqapi.add_local_variable( rtseq, variable_name, node_value) # add the local variable's accessor to the resources resources.add_variable(variable_name, node_value, rtseq_var_name) resources.add_variable(variable_name + ".value", node_value, rtseq_var_name) else: raise TranslateError(_errormessages.init_var_invalid_type) transformed_node_value = utils.generic_ast_node_transform( node.value, resources) rtseq_var_name = resources.get_variable_rtseq_name( variable_name) if not rtseq_var_name else rtseq_var_name if not initial_channel_ref_declaration: if isinstance(node_value, _datatypes.ArrayType): if transformed_node_value.count(',') > 0: value_list = transformed_node_value.split(',') for index, val in enumerate(value_list): rtseqapi.add_assignment( block, rtseq_var_name + "[" + str(index) + "]", val) else: rtseqapi.add_assignment(block, rtseq_var_name, transformed_node_value)
def _validate_restrictions(node): if node.orelse: raise TranslateError(_errormessages.for_else_not_supported) if not isinstance(node.iter, (ast.Name, ast.Attribute, ast.Call)): raise TranslateError(_errormessages.invalid_iterable_collection) if not isinstance(node.target, ast.Name): raise TranslateError(_errormessages.invalid_for_loop_iterator) if validations.check_if_any_in_block(ast.Return, node.body): raise TranslateError(_errormessages.return_unsupported_unless_last) if validations.check_if_any_in_block(ast.FunctionDef, node.body): raise TranslateError(_errormessages.invalid_nested_funcdef) validations.raise_if_try_in_node_body(node.body)
def get_value_from_node(node, resources): if isinstance(node, ast.Call): call = generic_ast_node_transform(node.func, resources) node_id = call.split('.')[-1] if rtprimitives.is_supported_data_type(node_id): datatype = rtprimitives.get_class_by_name(node.func.id) if rtprimitives.is_channel_ref_type(datatype.__name__): if rtprimitives.is_array_type(datatype.__name__): datavalue = [0.0] else: datavalue = 0.0 elif type(node.args[0]) is ast.UnaryOp or is_node_ast_num( node.args[0]): datavalue = get_element_value(node.args[0]) elif type(node.args[0]) is ast.Name: if node.args[0].id in symbols._symbols: datavalue = symbols._symbols[node.args[0].id] else: raise TranslateError(_errormessages.init_var_invalid_type) elif is_node_ast_nameconstant(node.args[0]): node_value = get_value_from_nameconstant_node(node.args[0]) if node_value is True or node_value is False: datavalue = node_value else: raise TranslateError(_errormessages.init_var_invalid_type) elif type(node.args[0]) is ast.List: datavalue = [ get_element_value(element) for element in node.args[0].elts ] else: raise TranslateError(_errormessages.init_var_invalid_type) return datatype(datavalue) elif isinstance(node, ast.Name): if node.id in ['True', 'False']: return _datatypes.BooleanValue(node.id) elif is_node_ast_num(node): node_value = get_value_from_num_node(node) if isinstance(node_value, int): try: return_obj = _datatypes.I32Value(node_value) except OverflowError: return_obj = _datatypes.I64Value(node_value) return return_obj elif isinstance(node_value, float): return _datatypes.DoubleValue(node_value) elif is_node_ast_nameconstant(node): node_value = get_value_from_nameconstant_node(node) if node_value is None: raise TranslateError(_errormessages.init_var_invalid_type) return _datatypes.BooleanValue(node_value) raise TranslateError(_errormessages.init_var_invalid_type)
def get_value_from_node(node, resources): if isinstance(node, ast.Call): call = generic_ast_node_transform(node.func, resources) node_id = call.split('.')[-1] if rtprimitives.is_supported_data_type(node_id): datatype = rtprimitives.get_class_by_name(node.func.id) if rtprimitives.is_channel_ref_type(datatype.__name__): if rtprimitives.is_array_type(datatype.__name__): datavalue = [0.0] else: datavalue = 0.0 elif type(node.args[0]) in (ast.Num, ast.UnaryOp): datavalue = get_element_value(node.args[0]) elif type(node.args[0]) is ast.Name: if node.args[0].id in symbols._symbols: datavalue = symbols._symbols[node.args[0].id] else: raise TranslateError(_errormessages.init_var_invalid_type) # this is ugly, but NameConstant does not exist in 2.7 and we need to evaluate the system version # otherwise the 2.7 version will error out by not recognizing the NameConstant attribute elif sys.version_info >= (3, 5) and type( node.args[0]) is ast.NameConstant: if node.args[0].value is True or node.args[0].value is False: datavalue = node.args[0].value else: raise TranslateError(_errormessages.init_var_invalid_type) elif type(node.args[0]) is ast.List: datavalue = [ get_element_value(element) for element in node.args[0].elts ] else: raise TranslateError(_errormessages.init_var_invalid_type) return datatype(datavalue) elif isinstance(node, ast.Num): if isinstance(node.n, int): try: return_obj = _datatypes.I32Value(node.n) except OverflowError: return_obj = _datatypes.I64Value(node.n) return return_obj elif isinstance(node.n, float): return _datatypes.DoubleValue(node.n) elif sys.version_info >= (3, 5) and isinstance(node, ast.NameConstant): if node.value is None: raise TranslateError(_errormessages.init_var_invalid_type) return _datatypes.BooleanValue(node.value) elif isinstance(node, ast.Name): if node.id in ['True', 'False']: return _datatypes.BooleanValue(node.id) raise TranslateError(_errormessages.init_var_invalid_type)
def get_element_value(node): if is_node_ast_num(node): return get_value_from_num_node(node) elif type(node) is ast.UnaryOp: return eval(generic_ast_node_transform(node, ())) elif type(node) is ast.Name: if node.id in symbols._symbols: return symbols._symbols[node.id] else: raise TranslateError(_errormessages.init_var_invalid_type) elif is_node_ast_nameconstant(node): return get_value_from_nameconstant_node(node) else: raise TranslateError(_errormessages.init_var_invalid_type)
def get_element_value(node): if type(node) is ast.Num: return node.n elif type(node) is ast.UnaryOp: return eval(generic_ast_node_transform(node, ())) elif type(node) is ast.Name: if node.id in symbols._symbols: return symbols._symbols[node.id] else: raise TranslateError(_errormessages.init_var_invalid_type) # this is ugly, but NameConstant does not exist in 2.7 and we need to evaluate the system version # otherwise the 2.7 version will error out by not recognizing the NameConstant attribute elif sys.version_info >= (3, 5) and type(node) is ast.NameConstant: return node.value else: raise TranslateError(_errormessages.init_var_invalid_type)
def name_transformer(node, resources): if node.id == 'None': raise TranslateError(_errormessages.none_not_supported) if node.id in symbols._symbols: return symbols._symbols[node.id] elif resources.has_variable(node.id): return resources.get_variable_rtseq_name(node.id) else: return node.id
def custom_generate_error(node, resources): _validate_restrictions(node) try: error_code = eval( utils.generic_ast_node_transform(node.args[0], resources)) except NameError: raise TranslateError( _errormessages.invalid_error_code_for_generate_error) message = node.args[1].s action = ErrorAction[node.args[2].attr] realtimesequencedefinition.add_generate_error( resources.get_current_block(), error_code, message, action.value) return ""
def compareoperator_transformer(node, resources): left = utils.generic_ast_node_transform(node.left, resources) result = "((" + left + ") " if len(node.ops) > 1: raise TranslateError( _errormessages.cascaded_comparison_operators_not_allowed) operator = _operator(node.ops[0].__class__.__name__) if operator == "unknown": raise VeristandNotImplementedError() right = utils.generic_ast_node_transform(node.comparators[0], resources) result += operator + " (" + right + ")" result += ")" return result
def _validate_restrictions(node): valid_types = [ast.Num, ast.Attribute] if sys.version_info > (3, 0): valid_types.append(ast.NameConstant) if not isinstance(node.value, tuple(valid_types)): raise TranslateError(_errormessages.invalid_return_type)
def _validate_restrictions(node): if not isinstance(node.args[0], ast.Name): raise TranslateError(_errormessages.invalid_taskname_for_stop_task)
def __getitem__(self, item): item = self._obj_to_key(item) seq = self._try_resolve(item) if seq is None: raise TranslateError(_errormessages.dependency_not_found) return self._rtseqs.get(item)
def save_referenced(self, path, referencer): for seq in self.get_referenced(referencer): if seq is None: raise TranslateError(_errormessages.dependency_not_found) seq.save(path)
def default_transformer(node, resources): raise TranslateError("Unexpected transform for node type %s" % node.__class__.__name__)
def _validate_restrictions(node): if not isinstance(node.value, ast.Attribute) and \ not utils.is_node_ast_nameconstant(node.value) and \ not utils.is_node_ast_num(node.value): raise TranslateError(_errormessages.invalid_return_type)
def except_transformer(node, resources): raise TranslateError(_errormessages.invalid_try_except_orelse)