예제 #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.")
예제 #2
0
    def __getitem__(self, dot_path):
        """
        Return the type of the given item.

        :type dot_path: ast.DotPath
        :param dot_path: The path to follow
        :return:
        """
        if self.ctor_properties is None:
            raise exception.BananaTypeCheckerBug(
                "Component type can't have properties")

        if len(dot_path.properties) == 0:
            for arg in self.ctor_properties:
                if arg.param_name == dot_path.varname.inner_val():
                    return arg.param_type
        else:
            for arg in self.ctor_properties:
                if arg.param_name == dot_path.varname.inner_val():
                    if isinstance(arg.param_type, Object):
                        return arg.param_type[dot_path.next_dot_path()]
                    else:
                        raise exception.BananaPropertyDoesNotExists(
                            dot_path.next_dot_path(), arg.param_type)

        raise exception.BananaPropertyDoesNotExists(dot_path, on_type=self)
예제 #3
0
    def __getitem__(self, key):
        # a.b or a."b"
        if isinstance(key, ast.Ident) or isinstance(key, ast.StringLit):
            if key.inner_val() not in self.props:
                raise exception.BananaPropertyDoesNotExists(key, on_type=self)
            return self.props[key.inner_val()]

        # a.b.c
        if isinstance(key, ast.DotPath):
            if key.varname.inner_val() not in self.props:
                raise exception.BananaPropertyDoesNotExists(key.varname,
                                                            on_type=self)
            sub_object = self.props[key.varname.inner_val()]
            if len(key.properties) == 0:
                return sub_object
            # Recurse
            if isinstance(sub_object, Object):
                return sub_object[key.next_dot_path()]
            if isinstance(sub_object, Any):
                return sub_object

            raise exception.BananaPropertyDoesNotExists(key.next_dot_path(),
                                                        on_type=sub_object)

        raise exception.BananaTypeCheckerBug(
            "Unreachable code in Object.__getitem__ reached.")
예제 #4
0
 def get_type(self, var, statement_index=None):
     variables = self.get_variables(statement_index)
     if isinstance(var, ast.Ident):
         if var in variables:
             return variables[var]
         else:
             raise exception.BananaUnknown(var)
     # If we encounter a dot path:
     if isinstance(var, ast.DotPath):
         if var.varname in variables:
             if len(var.properties) > 0:
                 return variables[var.varname][var.next_dot_path()]
             else:
                 return variables[var.varname]
         else:
             raise exception.BananaUnknown(var.varname)
     raise exception.BananaTypeCheckerBug("Unkown type for {}".format(var))
예제 #5
0
    def __setitem__(self, dot_path, value):
        """
        Attempt to set the value at 'dot_path' to 'value'.

        :type dot_path: ast.DotPath
        :param dot_path: The path of the property
        :type value: String | Enum | Object | Number
        :param value: The new type to set.
        """
        if self.ctor_properties is None:
            raise exception.BananaTypeCheckerBug(
                "Component type can't have properties")

        if len(dot_path.properties) == 0:
            for arg in self.ctor_properties:
                if arg.param_name == dot_path.varname.inner_val():
                    if not can_be_cast_to(value, arg.param_type):
                        raise exception.BananaArgumentTypeError(
                            expected_type=arg.param_type,
                            received_type=value,
                            where=dot_path.span)
                    else:
                        return
        else:
            for arg in self.ctor_properties:
                if arg.param_name == dot_path.varname.inner_val():
                    if isinstance(arg.param_type, Any):
                        return
                    elif isinstance(arg.param_type, Object):
                        next_dot_path = dot_path.next_dot_path()
                        sub_arg_type = arg.param_type[next_dot_path]
                        if not can_be_cast_to(value, sub_arg_type):
                            raise exception.BananaArgumentTypeError(
                                expected_type=sub_arg_type,
                                received_type=value,
                                where=next_dot_path.span)
                        else:
                            return
                    else:
                        raise exception.BananaPropertyDoesNotExists(
                            dot_path.next_dot_path(), arg.param_type)

        raise exception.BananaPropertyDoesNotExists(dot_path, on_type=self)
예제 #6
0
def typeck_component(component, type_table):
    """
    Type-check the provided component. Returns
    the appropriate subclass of util.Component if
    successful, or raise an exception if there's
    an error.
    :type component: ast.Component
    :param component: The component ast node.
    :type type_table: typetbl.TypeTable
    :param type_table: the type table.
    :rtype: u.Source | u.Sink | u.Voter | u.Ldp | u.Sml | u.Ingestor
    :return: Returns the appropriate type for the component.
    """
    # TODO(Joan): This wont't work for type that are defined
    # TODO(Joan): at the language level. We need a registration service
    # TODO(Joan): to manage the Types of component that we can create
    # TODO(Joan): instead of this hacky function call.
    try:
        component_type = introspect.get_class_by_name(component.type_name.val)
        comp_params = component_type.get_params()
    except exception_monanas.MonanasNoSuchClassError:
        raise exception.BananaUnknown(component)

    # Compute the type of the component
    if issubclass(component_type, source.BaseSource):
        comp_type = u.Source(component_type.__name__, comp_params)
    elif issubclass(component_type, sink.BaseSink):
        comp_type = u.Sink(component_type.__name__, comp_params)
    elif issubclass(component_type, sml.BaseSML):
        comp_type = u.Sml(component_type.__name__, comp_params)
    elif issubclass(component_type, voter.BaseVoter):
        comp_type = u.Voter(component_type.__name__, comp_params)
    elif issubclass(component_type, ldp.BaseLDP):
        comp_type = u.Ldp(component_type.__name__, comp_params)
    elif issubclass(component_type, ingestor.BaseIngestor):
        comp_type = u.Ingestor(component_type.__name__, comp_params)
    else:
        raise exception.BananaTypeCheckerBug(
            "Couldn't find a type for '{}'".format(component.type_name.val))

    # Type check the parameters
    if len(component.args) > len(comp_params):
        raise exception.BananaComponentTooManyParams(component.span)

    # Does saying that parameter should either all have a name
    # or non at all satisfying? -> Yes
    # Are parameter all named?
    all_named = -1
    for arg in component.args:
        if arg.arg_name is not None:
            if all_named == 0:
                raise exception.BananaComponentMixingParams(arg.span, False)
            all_named = 1
        else:
            if all_named == 1:
                raise exception.BananaComponentMixingParams(arg.span, True)
            all_named = 0

    if all_named == 1:
        for arg in component.args:
            param = filter(lambda x: x.param_name == arg.arg_name.inner_val(),
                           comp_params)
            if len(param) != 1:
                raise exception.BananaComponentIncorrectParamName(
                    component=component.type_name, found=arg.arg_name)
            param = param[0]
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type)
    else:
        for arg, param in zip(component.args, comp_params):
            arg.arg_name = ast.Ident(arg.span, param.param_name)
            expr_type = typeck_rhs(arg.value, type_table)
            if not u.can_be_cast_to(expr_type, param.param_type):
                raise exception.BananaArgumentTypeError(
                    where=arg,
                    expected_type=param.param_type,
                    received_type=expr_type)

    return comp_type