def _decorator_to_arg(node, resources): arg_name = def_value = by_value = None if not len(node.args) == 3: raise errors.TranslateError(_errormessages.invalid_param_decorator) # this is a decorator param definition. First parameter is the string for the name. if utils.is_node_ast_str(node.args[0]): arg_name = utils.get_value_from_str_node(node.args[0]) # second is the default value try: def_value = utils.get_value_from_node(node.args[1], resources) except errors.TranslateError: # def_value won't get assigned anything if an error occurs, which will trigger the exception later. pass # third is whether to pass by ref or by value valid_types = [ast.Name, ast.Attribute] if isinstance(node.args[2], tuple(valid_types)): by_value_str = utils.get_variable_name_from_node(node.args[2]) by_value_str = getattr(_decorators.NivsParam, by_value_str.split('.')[-1], by_value_str) by_value = BooleanValue(by_value_str).value elif 'NameConstant' in dir(ast) and utils.is_node_ast_nameconstant( node.args[2]): by_value = utils.get_value_from_nameconstant_node(node.args[2]) if arg_name is None or def_value is None or by_value is None: raise errors.TranslateError(_errormessages.invalid_param_decorator) return _param(arg_name, def_value, by_value)
def _validate_restrictions(node): if validations.check_if_any_in_block(ast.FunctionDef, node.body): raise errors.TranslateError(_errormessages.invalid_function_definition) if node.returns is not None \ or len(node.args.kwonlyargs) != 0 \ or len(node.args.kw_defaults) != 0 \ or node.args.vararg is not None \ or node.args.kwarg is not None \ or len(node.args.defaults) != 0: raise errors.TranslateError(_errormessages.invalid_function_definition) if validations.check_if_any_in_block(validations.ast_try(), node.body): if not isinstance(node.body[0], validations.ast_try()): raise errors.TranslateError(_errormessages.try_must_be_first_stmt) if len(node.body) > 2: raise errors.TranslateError(_errormessages.invalid_stmt_after_try) elif len(node.body) == 2: if not isinstance(node.body[1], ast.Return): raise errors.TranslateError( _errormessages.invalid_stmt_after_try) return_statements = [ statement for statement in node.body if isinstance(statement, ast.Return) ] if len(return_statements) > 1: raise errors.TranslateError(_errormessages.multiple_return_statements) if validations.check_if_any_in_block(ast.Return, node.body[:-1]): raise errors.TranslateError( _errormessages.return_unsupported_unless_last) for decorator in node.decorator_list: decorator_name_node = decorator.func if isinstance( decorator, ast.Call) else decorator decorator_name = utils.get_variable_name_from_node(decorator_name_node) decorator_name = decorator_name.split(".")[-1] _raise_if_invalid_decorator(decorator_name)
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 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 attribute_transformer(node, resources): var_name = utils.get_variable_name_from_node(node) if resources.has_variable(var_name): if isinstance(node.value, ast.Subscript): return utils.generic_ast_node_transform(node.value, resources) else: return resources.get_variable_rtseq_name(var_name) try: # Try to get the value of the node in case it's a DataType(x).value style. node_value = utils.get_value_from_node(node.value, resources) return str(node_value) except errors.TranslateError: # If we get a TranslateError it's because it wasn't a DataType(x).value, so move on. pass built_exp = utils.generic_ast_node_transform(node.value, resources) + '.' + node.attr if built_exp in symbols._symbols: return symbols._symbols[built_exp] else: raise errors.TranslateError(_errormessages.unknown_identifier % var_name)
def subscript_transformer(node, resources): variable_name = utils.get_variable_name_from_node(node) rtseq_var_name = resources.get_variable_rtseq_name(variable_name) index = utils.generic_ast_node_transform(node.slice, resources) return rtseq_var_name + "[" + index + "]"
def _get_name_without_namespace_from_node(node): return utils.get_variable_name_from_node(node).split('.')[-1]
def raise_if_invalid_if_test(node): if isinstance(node, ast.UnaryOp): node = node.operand if isinstance(node, ast.Call) and utils.get_variable_name_from_node(node.func) in VALID_TYPES: raise errors.TranslateError(_errormessages.invalid_type_for_if_test)