<commit_before>#
# UAVCAN DSDL file parser
#
# Copyright (C) 2014 <NAME> <<EMAIL>>
#

from __future__ import division, absolute_import, print_function, unicode_literals
import os, re, logging
from io import StringIO
from .signature import compute_signature
from .common import DsdlException, pretty_filename
from .type_limits import get_unsigned_integer_range, get_signed_integer_range, get_float_range

# Python 2.7 compatibility
try:
    str = unicode
except NameError:
    pass
try:
    long(1)
except NameError:
    long = int

MAX_FULL_TYPE_NAME_LEN = 80
DATA_TYPE_ID_MAX = 1023
MAX_DATA_STRUCT_LEN_BYTES = 439

class Type:
    '''
    Common type description. The specialized type description classes inherit from this one.
    Fields:
        full_name    Full type name string, e.g. "uavcan.protocol.NodeStatus"
        category     Any CATEGORY_*
    '''
    CATEGORY_PRIMITIVE = 0
    CATEGORY_ARRAY = 1
    CATEGORY_COMPOUND = 2

    def __init__(self, full_name, category):
        self.full_name = str(full_name)
        self.category = category

    def __str__(self):
        return self.get_normalized_definition()

    __repr__ = __str__

class PrimitiveType(Type):
    '''
    Primitive type description, e.g. bool or float16.
    Fields:
        kind         Any KIND_*
        bitlen       Bit length, 1 to 64
        cast_mode    Any CAST_MODE_*
        value_range  Tuple containing min and max values: (min, max)
    '''
    KIND_BOOLEAN = 0
    KIND_UNSIGNED_INT = 1
    KIND_SIGNED_INT = 2
    KIND_FLOAT = 3

    CAST_MODE_SATURATED = 0
    CAST_MODE_TRUNCATED = 1

    def __init__(self, kind, bitlen, cast_mode):
        self.kind = kind
        self.bitlen = bitlen
        self.cast_mode = cast_mode
        Type.__init__(self, self.get_normalized_definition(), Type.CATEGORY_PRIMITIVE)
        self.value_range = {
            PrimitiveType.KIND_BOOLEAN: get_unsigned_integer_range,
            PrimitiveType.KIND_UNSIGNED_INT: get_unsigned_integer_range,
            PrimitiveType.KIND_SIGNED_INT: get_signed_integer_range,
            PrimitiveType.KIND_FLOAT: get_float_range
        }[self.kind](bitlen)

    def get_normalized_definition(self):
        '''Please refer to the specification for details about normalized definitions.'''
        cast_mode = 'saturated' if self.cast_mode == PrimitiveType.CAST_MODE_SATURATED else 'truncated'
        primary_type = {
            PrimitiveType.KIND_BOOLEAN: 'bool',
            PrimitiveType.KIND_UNSIGNED_INT: 'uint' + str(self.bitlen),
            PrimitiveType.KIND_SIGNED_INT: 'int' + str(self.bitlen),
            PrimitiveType.KIND_FLOAT: 'float' + str(self.bitlen)
        }[self.kind]
        return cast_mode + ' ' + primary_type

    def validate_value_range(self, value):
        '''Checks value range, throws DsdlException if the value cannot be represented by this type.'''
        low, high = self.value_range
        if not low <= value <= high:
            error('Value [%s] is out of range %s', value, self.value_range)

    def get_max_bitlen(self):
        '''Returns type bit length.'''
        return self.bitlen

class ArrayType(Type):
    '''
    Array type description, e.g. float32[8], uint12[<34].
    Fields:
        value_type    Description of the array value type; the type of this field inherits Type, e.g. PrimitiveType
        mode          Any MODE_*
        max_size      Maximum number of elements in the array
    '''
    MODE_STATIC = 0
    MODE_DYNAMIC = 1

    def __init__(self, value_type, mode, max_size):
        self.value_type = value_type
        self.mode = mode
        self.max_size = max_size
        Type.__init__(self, self.get_normalized_definition(), Type.CATEGORY_ARRAY)

    def get_normalized_definition(self):
        '''Please refer to the specification for details about normalized definitions.'''
        typedef = self.value_type.get_normalized_definition()
        return ('%s[<=%d]' if self.mode == ArrayType.MODE_DYNAMIC else '%s[%d]') % (typedef, self.max_size)

    def get_max_bitlen(self):
        '''Returns total maximum bit length of the array, including length field if applicable.'''
        payload_max_bitlen = self.max_size * self.value_type.get_max_bitlen()
        return {
            self.MODE_DYNAMIC: payload_max_bitlen + self.max_size.bit_length(),
            self.MODE_STATIC: payload_max_bitlen
        }[self.mode]

class CompoundType(Type):
    '''
    Compound type description, e.g. uavcan.protocol.NodeStatus.
    Fields:
        source_file         Path to the DSDL definition file for this type
        default_dtid        Default Data Type ID, if specified, None otherwise
        kind                Any KIND_*
        source_text         Raw DSDL definition text (as is, with comments and the original formatting)
    
    Fields if kind == KIND_SERVICE:
        request_fields      Request struct field list, the type of each element is Field
        response_fields     Response struct field list
        request_constants   Request struct constant list, the type of each element is Constant
        response_constants  Response struct constant list
    
    Fields if kind == KIND_MESSAGE:
        fields              Field list, the type of each element is Field
        constants           Constant list, the type of each element is Constant
    
    Extra methods if kind == KIND_SERVICE:
        get_max_bitlen_request()    Returns maximum total bit length for the serialized request struct
        get_max_bitlen_response()   Same for the response struct
    
    Extra methods if kind == KIND_MESSAGE:
        get_max_bitlen()            Returns maximum total bit length for the serialized struct
    '''
    KIND_SERVICE = 0
    KIND_MESSAGE = 1

    def __init__(self, full_name, kind, source_file, default_dtid, source_text):
        Type.__init__(self, full_name, Type.CATEGORY_COMPOUND)
        self.source_file = source_file
        self.default_dtid = default_dtid
        self.kind = kind
        self.source_text = source_text
        max_bitlen_sum = lambda fields: sum([x.type.get_max_bitlen() for x in fields])
        if kind == CompoundType.KIND_SERVICE:
            self.request_fields = []
            self.response_fields = []
            self.request_constants = []
            self.response_constants = []
            self.get_max_bitlen_request = lambda: max_bitlen_sum(self.request_fields)
            self.get_max_bitlen_response = lambda: max_bitlen_sum(self.response_fields)
        elif kind == CompoundType.KIND_MESSAGE:
            self.fields = []
            self.constants = []
            self.get_max_bitlen = lambda: max_bitlen_sum(self.fields)
        else:
            error('Compound type of unknown kind [%s]', kind)

    def get_dsdl_signature_source_definition(self):
        '''
        Returns normalized DSDL definition text.
        Please refer to the specification for details about normalized DSDL definitions.
        '''
        txt = StringIO()
        txt.write(self.full_name + '\n')
        adjoin = lambda attrs: txt.write('\n'.join(x.get_normalized_definition() for x in attrs) + '\n')
        const_sort_key = lambda x: x.get_normalized_definition()
        if self.kind == CompoundType.KIND_SERVICE:
            adjoin(self.request_fields)
            adjoin(sorted(self.request_constants, key=const_sort_key))
            txt.write('\n---\n')
            adjoin(self.response_fields)
            adjoin(sorted(self.response_constants, key=const_sort_key))
        elif self.kind == CompoundType.KIND_MESSAGE:
            adjoin(self.fields)
            adjoin(sorted(self.constants, key=const_sort_key))
        else:
            error('Compound type of unknown kind [%s]', self.kind)
        return txt.getvalue().strip().replace('\n\n\n', '\n').replace('\n\n', '\n')

    def get_dsdl_signature(self):
        '''
        Computes DSDL signature of this type.
        Please refer to the specification for details about signatures.
        '''
        return compute_signature(self.get_dsdl_signature_source_definition())

    def get_normalized_definition(self):
        '''Returns full type name string, e.g. "uavcan.protocol.NodeStatus"'''
        return self.full_name


class Attribute:
    '''
    Base class of an attribute description.
    Fields:
        type    Attribute type description, the type of this field inherits the class Type, e.g. PrimitiveType
        name    Attribute name string
    '''
    def __init__(self, type, name):  # @ReservedAssignment<commit_msg>DSDL signature does not depend on constant definitions anymore (see specification)<commit_after>#
# UAVCAN DSDL file parser
#
# Copyright (C) 2014 <NAME> <<EMAIL>>
#

from __future__ import division, absolute_import, print_function, unicode_literals
import os, re, logging
from io import StringIO
from .signature import compute_signature
from .common import DsdlException, pretty_filename
from .type_limits import get_unsigned_integer_range, get_signed_integer_range, get_float_range

# Python 2.7 compatibility
try:
    str = unicode
except NameError:
    pass
try:
    long(1)
except NameError:
    long = int

MAX_FULL_TYPE_NAME_LEN = 80
DATA_TYPE_ID_MAX = 1023
MAX_DATA_STRUCT_LEN_BYTES = 439

class Type:
    '''
    Common type description. The specialized type description classes inherit from this one.
    Fields:
        full_name    Full type name string, e.g. "uavcan.protocol.NodeStatus"
        category     Any CATEGORY_*
    '''
    CATEGORY_PRIMITIVE = 0
    CATEGORY_ARRAY = 1
    CATEGORY_COMPOUND = 2

    def __init__(self, full_name, category):
        self.full_name = str(full_name)
        self.category = category

    def __str__(self):
        return self.get_normalized_definition()

    __repr__ = __str__

class PrimitiveType(Type):
    '''
    Primitive type description, e.g. bool or float16.
    Fields:
        kind         Any KIND_*
        bitlen       Bit length, 1 to 64
        cast_mode    Any CAST_MODE_*
        value_range  Tuple containing min and max values: (min, max)
    '''
    KIND_BOOLEAN = 0
    KIND_UNSIGNED_INT = 1
    KIND_SIGNED_INT = 2
    KIND_FLOAT = 3

    CAST_MODE_SATURATED = 0
    CAST_MODE_TRUNCATED = 1

    def __init__(self, kind, bitlen, cast_mode):
        self.kind = kind
        self.bitlen = bitlen
        self.cast_mode = cast_mode
        Type.__init__(self, self.get_normalized_definition(), Type.CATEGORY_PRIMITIVE)
        self.value_range = {
            PrimitiveType.KIND_BOOLEAN: get_unsigned_integer_range,
            PrimitiveType.KIND_UNSIGNED_INT: get_unsigned_integer_range,
            PrimitiveType.KIND_SIGNED_INT: get_signed_integer_range,
            PrimitiveType.KIND_FLOAT: get_float_range
        }[self.kind](bitlen)

    def get_normalized_definition(self):
        '''Please refer to the specification for details about normalized definitions.'''
        cast_mode = 'saturated' if self.cast_mode == PrimitiveType.CAST_MODE_SATURATED else 'truncated'
        primary_type = {
            PrimitiveType.KIND_BOOLEAN: 'bool',
            PrimitiveType.KIND_UNSIGNED_INT: 'uint' + str(self.bitlen),
            PrimitiveType.KIND_SIGNED_INT: 'int' + str(self.bitlen),
            PrimitiveType.KIND_FLOAT: 'float' + str(self.bitlen)
        }[self.kind]
        return cast_mode + ' ' + primary_type

    def validate_value_range(self, value):
        '''Checks value range, throws DsdlException if the value cannot be represented by this type.'''
        low, high = self.value_range
        if not low <= value <= high:
            error('Value [%s] is out of range %s', value, self.value_range)

    def get_max_bitlen(self):
        '''Returns type bit length.'''
        return self.bitlen

class ArrayType(Type):
    '''
    Array type description, e.g. float32[8], uint12[<34].
    Fields:
        value_type    Description of the array value type; the type of this field inherits Type, e.g. PrimitiveType
        mode          Any MODE_*
        max_size      Maximum number of elements in the array
    '''
    MODE_STATIC = 0
    MODE_DYNAMIC = 1

    def __init__(self, value_type, mode, max_size):
        self.value_type = value_type
        self.mode = mode
        self.max_size = max_size
        Type.__init__(self, self.get_normalized_definition(), Type.CATEGORY_ARRAY)

    def get_normalized_definition(self):
        '''Please refer to the specification for details about normalized definitions.'''
        typedef = self.value_type.get_normalized_definition()
        return ('%s[<=%d]' if self.mode == ArrayType.MODE_DYNAMIC else '%s[%d]') % (typedef, self.max_size)

    def get_max_bitlen(self):
        '''Returns total maximum bit length of the array, including length field if applicable.'''
        payload_max_bitlen = self.max_size * self.value_type.get_max_bitlen()
        return {
            self.MODE_DYNAMIC: payload_max_bitlen + self.max_size.bit_length(),
            self.MODE_STATIC: payload_max_bitlen
        }[self.mode]

class CompoundType(Type):
    '''
    Compound type description, e.g. uavcan.protocol.NodeStatus.
    Fields:
        source_file         Path to the DSDL definition file for this type
        default_dtid        Default Data Type ID, if specified, None otherwise
        kind                Any KIND_*
        source_text         Raw DSDL definition text (as is, with comments and the original formatting)
    
    Fields if kind == KIND_SERVICE:
        request_fields      Request struct field list, the type of each element is Field
        response_fields     Response struct field list
        request_constants   Request struct constant list, the type of each element is Constant
        response_constants  Response struct constant list
    
    Fields if kind == KIND_MESSAGE:
        fields              Field list, the type of each element is Field
        constants           Constant list, the type of each element is Constant
    
    Extra methods if kind == KIND_SERVICE:
        get_max_bitlen_request()    Returns maximum total bit length for the serialized request struct
        get_max_bitlen_response()   Same for the response struct
    
    Extra methods if kind == KIND_MESSAGE:
        get_max_bitlen()            Returns maximum total bit length for the serialized struct
    '''
    KIND_SERVICE = 0
    KIND_MESSAGE = 1

    def __init__(self, full_name, kind, source_file, default_dtid, source_text):
        Type.__init__(self, full_name, Type.CATEGORY_COMPOUND)
        self.source_file = source_file
        self.default_dtid = default_dtid
        self.kind = kind
        self.source_text = source_text
        max_bitlen_sum = lambda fields: sum([x.type.get_max_bitlen() for x in fields])
        if kind == CompoundType.KIND_SERVICE:
            self.request_fields = []
            self.response_fields = []
            self.request_constants = []
            self.response_constants = []
            self.get_max_bitlen_request = lambda: max_bitlen_sum(self.request_fields)
            self.get_max_bitlen_response = lambda: max_bitlen_sum(self.response_fields)
        elif kind == CompoundType.KIND_MESSAGE:
            self.fields = []
            self.constants = []
            self.get_max_bitlen = lambda: max_bitlen_sum(self.fields)
        else:
            error('Compound type of unknown kind [%s]', kind)

    def get_dsdl_signature_source_definition(self):
        '''
        Returns normalized DSDL definition text.
        Please refer to the specification for details about normalized DSDL definitions.
        '''
        txt = StringIO()
        txt.write(self.full_name + '\n')
        adjoin = lambda attrs: txt.write('\n'.join(x.get_normalized_definition() for x in attrs) + '\n')
        if self.kind == CompoundType.KIND_SERVICE:
            adjoin(self.request_fields)
            txt.write('\n---\n')
            adjoin(self.response_fields)
        elif self.kind == CompoundType.KIND_MESSAGE:
            adjoin(self.fields)
        else:
            error('Compound type of unknown kind [%s]', self.kind)
        return txt.getvalue().strip().replace('\n\n\n', '\n').replace('\n\n', '\n')

    def get_dsdl_signature(self):
        '''
        Computes DSDL signature of this type.
        Please refer to the specification for details about signatures.
        '''
        return compute_signature(self.get_dsdl_signature_source_definition())

    def get_normalized_definition(self):
        '''Returns full type name string, e.g. "uavcan.protocol.NodeStatus"'''
        return self.full_name


class Attribute:
    '''
    Base class of an attribute description.
    Fields:
        type    Attribute type description, the type of this field inherits the class Type, e.g. PrimitiveType
        name    Attribute name string
    '''
    def __init__(self, type, name):  # @ReservedAssignment
{'fraction_non_alphanumeric': 0.08090154211150652, 'fraction_numerical': 0.004863582443653618, 'mean_word_length': 2.643258426966292, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5264676', 'n_tokens_mistral': 4996, 'n_tokens_neox': 4859, 'n_words': 1359}