def execute(self, sensor_graph, scope_stack):
        """Execute this statement on the sensor_graph given the current scope tree.

        This adds a single config variable assignment to the current sensor graph

        Args:
            sensor_graph (SensorGraph): The sensor graph that we are building or
                modifying
            scope_stack (list(Scope)): A stack of nested scopes that may influence
                how this statement allocates clocks or other stream resources.
        """

        parent = scope_stack[-1]

        try:
            slot = parent.resolve_identifier('current_slot', SlotIdentifier)
        except UnresolvedIdentifierError:
            raise SensorGraphSemanticError("set config statement used outside of config block")

        if self.explicit_type is None or not isinstance(self.identifier, int):
            raise SensorGraphSemanticError("Config variable type definitions are not yet supported")

        if isinstance(self.value, (bytes, bytearray)) and not self.explicit_type == 'binary':
            raise SensorGraphSemanticError("You must pass the binary variable type when using encoded binary data")

        if not isinstance(self.value, (bytes, bytearray)) and self.explicit_type == 'binary':
            raise SensorGraphSemanticError("You must pass an encoded binary value with binary type config variables")

        sensor_graph.add_config(slot, self.identifier, self.explicit_type, self.value)
Beispiel #2
0
    def trigger_chain(self):
        """Return a NodeInput tuple for creating a node.

        Returns:
            (StreamIdentifier, InputTrigger)
        """

        raise SensorGraphSemanticError(
            "There is no trigger chain in this scope since no triggering criteria have been set",
            scope=self.name)
Beispiel #3
0
    def __init__(self, parsed, location=None):
        realtime = 'realtime' in parsed
        broadcast = 'broadcast' in parsed
        encrypted = 'security' in parsed and parsed['security'] == 'encrypted'
        signed = 'security' in parsed and parsed['security'] == 'signed'
        self.auto = 'manual' not in parsed

        self.with_other = None
        if 'with_other' in parsed:
            self.with_other = parsed['with_other']
            self.auto = False

        dest = SlotIdentifier.FromString('controller')
        if 'explicit_tile' in parsed:
            dest = parsed['explicit_tile']

        selector = parsed['selector']

        # Make sure all of the combination are valid
        if realtime and (encrypted or signed):
            raise SensorGraphSemanticError(
                "Realtime streamers cannot be either signed or encrypted")

        if broadcast and (encrypted or signed):
            raise SensorGraphSemanticError(
                "Broadcast streamers cannot be either signed or encrypted")

        super(StreamerStatement, self).__init__([], location)

        self.report_type = 'broadcast' if broadcast else 'telegram'
        self.dest = dest
        self.selector = selector

        if realtime or broadcast:
            self.report_format = u'individual'
        elif signed:
            self.report_format = u'signedlist_userkey'
        elif encrypted:
            raise SensorGraphSemanticError(
                "Encrypted streamers are not yet supported")
        else:
            self.report_format = u'hashedlist'
Beispiel #4
0
    def execute(self, sensor_graph, scope_stack):
        """Execute this statement on the sensor_graph given the current scope tree.

        This adds a single node to the sensor graph with subtract as the function
        so that the current scope's trigger stream has the subtract_stream's value
        subtracted from it.

        Args:
            sensor_graph (SensorGraph): The sensor graph that we are building or
                modifying
            scope_stack (list(Scope)): A stack of nested scopes that may influence
                how this statement allocates clocks or other stream resources.
        """

        if self.subtract_stream.stream_type != DataStream.ConstantType:
            raise SensorGraphSemanticError(
                "You can only subtract a constant value currently",
                stream=self.subtract_stream)

        parent = scope_stack[-1]
        alloc = parent.allocator

        trigger_stream, trigger_cond = parent.trigger_chain()

        sensor_graph.add_node(u"({} always && {} {}) => {} using {}".format(
            self.subtract_stream, trigger_stream, trigger_cond, self.stream,
            'subtract_afromb'))

        value = self.default
        if value is None:
            value = 0

        if self.default is not None and self.subtract_stream in sensor_graph.constant_database:
            raise SensorGraphSemanticError(
                "Attempted to set the same constant stream twice",
                stream=self.subtract_stream,
                new_value=self.default)
        elif self.default is None and self.subtract_stream in sensor_graph.constant_database:
            return

        sensor_graph.add_constant(self.subtract_stream, value)
Beispiel #5
0
    def clock(self, interval, basis):
        """Return a NodeInput tuple for triggering an event every interval.

        Args:
            interval (int): The interval (in seconds) at which this input should
                trigger.
            basis (str): The basis to use for calculating the interval.  This
                can either be system, tick_1 or tick_2.  System means that the
                clock will use either the fast or regular builtin tick.  Passing
                tick_1 or tick_2 will cause the clock to be generated based on
                the selected tick.
        """

        raise SensorGraphSemanticError(
            "There is not default clock defined in this scope",
            scope=self.name)
Beispiel #6
0
    def execute(self, sensor_graph, scope_stack):
        """Execute this statement on the sensor_graph given the current scope tree.

        This function will likely modify the sensor_graph and will possibly
        also add to or remove from the scope_tree.  If there are children nodes
        they will be called after execute_before and before execute_after,
        allowing block statements to sandwich their children in setup and teardown
        functions.

        Args:
            sensor_graph (SensorGraph): The sensor graph that we are building or
                modifying
            scope_stack (list(Scope)): A stack of nested scopes that may influence
                how this statement allocates clocks or other stream resources.
        """

        if not isinstance(scope_stack[-1], RootScope):
            raise SensorGraphSemanticError(
                "You may only declare metadata at global scope in a sensorgraph.",
                identifier=self.identifier,
                value=self.value)

        sensor_graph.add_metadata(self.identifier, self.value)
Beispiel #7
0
    def parse_statement(self, statement, orig_contents):
        """Parse a statement, possibly called recursively.

        Args:
            statement (int, ParseResult): The pyparsing parse result that
                contains one statement prepended with the match location
            orig_contents (str): The original contents of the file that we're
                parsing in case we need to convert an index into a line, column
                pair.

        Returns:
            SensorGraphStatement: The parsed statement.
        """

        children = []
        is_block = False
        name = statement.getName()

        # Recursively parse all children statements in a block
        # before parsing the block itself.
        # If this is a non-block statement, parse it using the statement
        # parser to figure out what specific statement it is before
        # processing it further.
        # This two step process produces better syntax error messsages
        if name == 'block':
            children_statements = statement[1]
            for child in children_statements:
                parsed = self.parse_statement(child,
                                              orig_contents=orig_contents)
                children.append(parsed)

            locn = statement[0]['location']
            statement = statement[0][1]
            name = statement.getName()
            is_block = True
        else:
            stmt_language = get_statement()
            locn = statement['location']
            statement = statement['match']
            statement_string = str(u"".join(statement.asList()))

            # Try to parse this generic statement into an actual statement.
            # Do this here in a separate step so we have good error messages when there
            # is a problem parsing a step.
            try:
                statement = stmt_language.parseString(statement_string)[0]
            except (pyparsing.ParseException,
                    pyparsing.ParseSyntaxException) as exc:
                raise SensorGraphSyntaxError(
                    "Error parsing statement in sensor graph file",
                    message=exc.msg,
                    line=pyparsing.line(locn, orig_contents).strip(),
                    line_number=pyparsing.lineno(locn, orig_contents),
                    column=pyparsing.col(locn, orig_contents))
            except SensorGraphSemanticError as exc:
                # Reraise semantic errors with line information
                raise SensorGraphSemanticError(
                    exc.msg,
                    line=pyparsing.line(locn, orig_contents).strip(),
                    line_number=pyparsing.lineno(locn, orig_contents),
                    **exc.params)

            name = statement.getName()

        if name not in statement_map:
            raise ArgumentError("Unknown statement in sensor graph file",
                                parsed_statement=statement,
                                name=name)

        # Save off our location information so we can give good error and warning information
        line = pyparsing.line(locn, orig_contents).strip()
        line_number = pyparsing.lineno(locn, orig_contents)
        column = pyparsing.col(locn, orig_contents)
        location_info = LocationInfo(line, line_number, column)

        if is_block:
            return statement_map[name](statement,
                                       children=children,
                                       location=location_info)

        return statement_map[name](statement, location_info)