Beispiel #1
0
    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 call_transformer(node, resources):
    if rtprimitives.is_channel_ref_type(node.func.id):
        if utils.is_node_ast_str(node.args[0]):
            node_value = utils.get_value_from_str_node(node.args[0])
            identifier = resources.get_channel_ref_rtseq_name_from_channel_name(node_value)
        else:
            raise errors.TranslateError(_errormessages.invalid_type_for_channel_ref)
        return identifier
    if rtprimitives.is_supported_data_type(node.func.id):
        if rtprimitives.is_scalar_type(node.func.id):
            return _transform_data_type_scalar(node)
        elif isinstance(node.args[0], ast.List):
            return _transform_datatype_non_scalar(node, resources)
        else:
            raise errors.TranslateError(_errormessages.init_var_invalid_type)
    if node.func.id in custom_action_symbols._custom_action_symbols:
        # Custom action symbols are basically transformers for functions that don't have
        # their own ast node. Invoke them here
        return custom_action_symbols._custom_action_symbols[node.func.id](node, resources)
    if node.func.id in symbols._symbols:
        # In case of a builtin expression get it out from symbols and add any arguments it may have
        func_name = symbols._symbols[node.func.id]
    else:
        # It only can be a RT sequence call, so treat it accordingly
        func_name = str(utils.generic_ast_node_transform(node.func, resources))
        resources.add_referenced_sequence(func_name)
    node_str = func_name + "("
    for arg in node.args:
        node_str += str(utils.generic_ast_node_transform(arg, resources))
        node_str += " ,"
    if not node.args:
        return node_str + ")"
    else:
        # remove space and comma
        return node_str[:-2] + ")"
Beispiel #3
0
def try_transformer(node, resources):
    _validate_restrictions(node)
    for stmt in node.body:
        utils.generic_ast_node_transform(stmt, resources)
    resources.set_current_block(resources.get_rtseq().Code.CleanUp)
    for stmt in node.finalbody:
        utils.generic_ast_node_transform(stmt, resources)
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 while_transformer(node, resources):
    _validate_restrictions(node, resources)
    test_condition = utils.generic_ast_node_transform(node.test, resources)
    parent_block = resources.get_current_block()
    while_statement = rtseqapi.add_while(parent_block, test_condition)
    for statement in node.body:
        resources.set_current_block(while_statement.Body)
        utils.generic_ast_node_transform(statement, resources)
    resources.set_current_block(parent_block)
Beispiel #6
0
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)
Beispiel #7
0
def binaryoperator_transformer(node, resources):
    operator = _operator(node.op.__class__.__name__)
    if operator == "unknown":
        raise VeristandNotImplementedError()
    if operator in ('<<', '>>'):
        # Validate only the right hand side, on the left it makes sense to have negative numbers.
        validations.raise_if_negative_binary_operator_operand(
            node.right, resources)
    left = utils.generic_ast_node_transform(node.left, resources)
    right = utils.generic_ast_node_transform(node.right, resources)
    return "((" + left + ") " + operator + " (" + right + "))"
def if_transformer(node, resources):
    _validate_restrictions(node)
    test_condition = utils.generic_ast_node_transform(node.test, resources)
    parent_block = resources.get_current_block()
    if_else_statement = rtseqapi.add_if_else(parent_block, test_condition)
    for statement in node.body:
        resources.set_current_block(if_else_statement.IfTrue)
        utils.generic_ast_node_transform(statement, resources)
    for statement in node.orelse:
        resources.set_current_block(if_else_statement.IfFalse)
        utils.generic_ast_node_transform(statement, resources)
    resources.set_current_block(parent_block)
Beispiel #9
0
def booloperator_transformer(node, resources):
    operator = _operator(node.op.__class__.__name__)
    if operator == "unknown":
        raise VeristandNotImplementedError()
    for value in node.values:
        validations.raise_if_invalid_bool_operand(value, resources)
    result = "( " + utils.generic_ast_node_transform(node.values[0],
                                                     resources) + " "
    for o in node.values[1:]:
        op = utils.generic_ast_node_transform(o, resources)
        result += operator + " " + op + " "
    return result + ")"
Beispiel #10
0
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
Beispiel #11
0
def with_transformer(node, resources):
    mt_name = _validate_multitask(node)
    parent_block = resources.get_current_block()
    multi_task = rtseqapi.add_multi_task(parent_block)
    for task_def in [
            func_def for func_def in node.body
            if isinstance(func_def, ast.FunctionDef)
    ]:
        _validate_task(task_def, mt_name)
        task_block = rtseqapi.add_task(multi_task, task_def.name)
        resources.set_current_block(task_block)
        for stmt in task_def.body:
            utils.generic_ast_node_transform(stmt, 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 _init_args(node, resources):
    # default values for now
    by_value = False
    def_value = DoubleValue(0)
    if type(node) is ast.Name:
        arg_name = utils.generic_ast_node_transform(node, resources)
    elif 'arg' in dir(ast) and type(node) is ast.arg:
        arg_name = node.arg
    return _param(arg_name, def_value, by_value)
Beispiel #14
0
def list_transformer(node, resources):
    list_string = ""
    if not node.elts:
        return list_string
    else:
        for element in node.elts:
            list_string += utils.generic_ast_node_transform(
                element, resources) + ","
        return list_string[:-1]
def exp_transformer(node, resources):
    if validations.check_if_looks_like_doc_block(node):
        exp = ""
    else:
        exp = utils.generic_ast_node_transform(node.value, resources)
    if bool(exp):
        # Custom actions generate their own expressions and return None
        # so only add an expression if something was returned
        rtseqapi.add_expression(resources.get_current_block(), exp)
    return exp
def functiondef_transformer(node, resources):
    if validations.check_if_looks_like_doc_block(node.body[0]):
        node.body = node.body[1:]
    _validate_restrictions(node)
    for param in node.args.args:
        p = _init_args(param, resources)
        resources.add_parameter(p.name, p.def_value, p.by_value)
    for decorator in [
            dec for dec in node.decorator_list if type(dec) is ast.Call
    ]:
        # the NivsParam decorator is a class, so it gets used like this:
        # @NivsParam(param_name, DataType(default), BY_REF)
        # which in ast terms is treated as an ast.Call. So, we look for those and convert to args.
        p = _decorator_to_arg(decorator, resources)
        resources.update_parameter(p.name, p.def_value, p.by_value)
    # reparenting should happen in each transformer that contains nested blocks
    resources.set_current_block(resources.get_rtseq().Code.Main.Body)
    for instruction in node.body:
        utils.generic_ast_node_transform(instruction, resources)
    return ""
Beispiel #17
0
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)
Beispiel #18
0
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 ""
Beispiel #19
0
def unaryoperator_transformer(node, resources):
    operator = _operator(node.op.__class__.__name__)
    if operator == "unknown":
        raise VeristandNotImplementedError()
    if operator == '!':
        if isinstance(node.operand, ast.UnaryOp):
            validations.raise_if_invalid_bool_operand(node.operand.operand, resources)
        else:
            validations.raise_if_invalid_bool_operand(node.operand, resources)
    if operator == '~':
        validations.raise_if_invalid_invert_operand(node.operand, resources)
    operand = utils.generic_ast_node_transform(node.operand, resources)
    return "(" + operator + "(" + operand + ")" + ")"
def custom_math_log(node, resources):
    if len(node.args) == 1:
        func = 'ln'
    else:
        func = 'log'

    node_str = func + "("
    for arg in node.args:
        node_str += str(utils.generic_ast_node_transform(arg, resources))
        node_str += " ,"
    if not node.args:
        return node_str + ")"
    else:
        # remove space and comma
        return node_str[:-2] + ")"
Beispiel #21
0
def ifexp_transformer(node, resources):
    validations.raise_if_invalid_if_test(node.test)
    test = utils.generic_ast_node_transform(node.test, resources)
    body = utils.generic_ast_node_transform(node.body, resources)
    orelse = utils.generic_ast_node_transform(node.orelse, resources)
    return "(" + test + ") ? (" + body + ") : (" + orelse + ")"
Beispiel #22
0
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 index_transformer(node, resources):
    index = utils.generic_ast_node_transform(node.value, resources)
    return index
def augassign_transformer(node, resources):
    bin_op = ast.BinOp(node.target, node.op, node.value)
    assign_node = ast.Assign([node.target], bin_op)
    return utils.generic_ast_node_transform(assign_node, resources)
def _transform_datatype_non_scalar(node, resources):
    data_value_str = utils.generic_ast_node_transform(node.args[0], resources)
    return data_value_str
Beispiel #26
0
def module_transformer(node, resources):
    rtseqfuncs = [rtf for rtf in ast.iter_child_nodes(node) if
                  type(rtf) is ast.FunctionDef and _has_rtseq_decorator(rtf)]
    for rtseqfunc in rtseqfuncs:
        utils.generic_ast_node_transform(rtseqfunc, resources)
    return ""