Beispiel #1
0
    def set_type(self, var, _type, statement_index):
        """
        Set the type for the given var to _type.

        :type var: ast.Ident | ast.DotPath
        :param var: The var to set a type.
        :type _type: util.Object | util.Component | util.String | util.Number
        :param _type: The type for the var.
        :type statement_index: int
        :param statement_index: The statement at which this assignment was
                                made.
        """
        if _type is None:
            raise exception.BananaTypeCheckerBug(
                "'None' is not a valid banana type"
            )

        if isinstance(var, ast.Ident):
            self._check_needs_for_snapshot(var, _type, statement_index)
            self._variables[var] = _type
            return

        if isinstance(var, ast.DotPath):
            if util.is_comp(_type) and len(var.properties) > 0:
                raise exception.BananaAssignCompError(var.span)

            if len(var.properties) == 0:
                self._check_needs_for_snapshot(
                    var.varname,
                    _type,
                    statement_index
                )
                self._variables[var.varname] = _type
            else:
                if var.varname in self._variables:
                    var_type = self._variables[var.varname]
                    if isinstance(var_type, util.Object):
                        new_type = util.create_object_tree(
                            var.next_dot_path(), _type)
                        util.attach_to_root(var_type, new_type, var.span,
                                            erase_existing=True)
                    elif isinstance(var_type, util.Component):
                        var_type[var.next_dot_path()] = _type
                    else:
                        raise exception.BananaTypeError(
                            expected_type=util.Object,
                            found_type=type(var)
                        )
                # Var undeclared, declare its own type
                else:
                    new_type = util.create_object_tree(var.next_dot_path(),
                                                       _type)
                    self._variables[var.varname] = new_type
            return
        raise exception.BananaTypeCheckerBug("Unreachable code reached.")
Beispiel #2
0
def create_object_tree(dot_path, value):
    """
    Create a linear tree of object type from the dot_path.
    Also work when dot_path is an Ident or StringLit.

    :type dot_path: ast.DotPath | ast.Ident | ast.StringLit
    :param dot_path: The ast node that forms a linear tree of type.
    :type value: Object | String | Number
    :param value: the value to set at the end of the linear tree.
    :rtype: Object
    :return: Returns the created object
    """
    if is_comp(value):
        raise exception.BananaAssignCompError(dot_path.span)

    # {a.b.c: value}
    root_object = Object(strict_checking=False)
    if isinstance(dot_path, ast.DotPath):
        # {a: value}
        if len(dot_path.properties) == 0:
            root_object.props[dot_path.varname.inner_val()] = value
        else:
            # {a: <Object>}
            root_object.props[dot_path.varname.inner_val()] = \
                Object(strict_checking=False)
            # {b.c: value}
            current_obj = root_object.props[dot_path.varname.inner_val()]
            last_index = len(dot_path.properties) - 1
            for index, sub_prop in enumerate(dot_path.properties):
                sub_prop_name = sub_prop.inner_val()
                if index != last_index:
                    current_obj.props[sub_prop_name] = \
                        Object(strict_checking=False)
                    current_obj = current_obj.props[sub_prop_name]
                else:
                    current_obj.props[sub_prop_name] = value
    else:
        # Ident and StringLit are captured here.
        root_object.props[dot_path.inner_val()] = value
    return root_object