Ejemplo n.º 1
0
    def add_field(self, field):
        field.dclass = ref(self)

        if isinstance(field, MolecularField):
            field.subfields = [proxy(self[name]) for name in field.subfields]
            field.resolve_keywords()

        if field.name:
            if field.name == self.name:
                if not self.is_struct:
                    raise DCParseError('A non-network field cannot be stored on a dclass')

                if self.constructor is not None:
                    raise DCParseError('Duplicate constructor for %s.' % self.name)

                if not isinstance(field, AtomicField):
                    raise DCParseError('Constructor fields must be atomic fields. Received %s instead.' % field.__class__)

                self.fields_by_name[field.name] = field
                self.constructor = field
                return

            if field.name in self.fields_by_name:
                raise DCParseError('duplicate field name', field.name)

            self.fields_by_name[field.name] = field

        self.dcfile().add_field(field)

        if field.number in self.fields_by_index:
            raise DCParseError

        self.fields_by_index[field.number] = field

        self.fields.append(field)
Ejemplo n.º 2
0
    def constrained_float_type(self, args):
        token = args.pop(0)
        ranges = []
        modulus = None
        divisor = 1

        while args:
            v = args.pop(0)

            if isinstance(v, Tree):
                if v.data == 'float_ranges':
                    ranges = tuple(r.children for r in v.children)
                if v.data == 'float_transform':
                    modulus, divisor = v.children

        if modulus is not None and modulus < 0:
            raise DCParseError('Negative modulus not allowed.')

        if divisor == 0:
            raise DCParseError('Division by zero')

        if divisor < 0:
            raise DCParseError('Negative divisor not allowed.')

        return Tree('constrained_float_type', [token, ranges, modulus, divisor])
Ejemplo n.º 3
0
    def resolve_type(self, identifier):
        type_obj = None
        type_info = None

        while type_obj is None:
            try:
                if hasattr(DCTypes, identifier):
                    type_obj = identifier
                    break

                obj = self.namespace[identifier]

                if isinstance(obj, TypeDef):
                    identifier = obj.old_type
                    if type_info is not None and type_info[3] is not None and obj.aranges is not None:
                        aranges = type_info[3] + obj.aranges
                    else:
                        aranges = obj.aranges

                    type_info = (obj.ranges, obj.modulus, obj.divisor, aranges)
                else:
                    type_obj = obj

            except KeyError:
                raise DCParseError('unknown type', identifier)

        return type_obj, type_info
Ejemplo n.º 4
0
 def pack_value(self, dg, args):
     # Allow generator usage for getters while also ensuring we pack all required parameters.
     it = zip(self.parameters, args)
     try:
         for _ in range(len(self.parameters)):
             parameter, arg = next(it)
             parameter.pack_value(dg, arg)
     except StopIteration:
         raise DCParseError(f'Missing parameters for field: {self.name}. args={list(args)}')
Ejemplo n.º 5
0
    def pack_value(self, dg, value):
        if not self.validate_value(value):
            raise DCParseError(f'value `{value}` not in range for type `{self.dtype}/{self.divisor if self.divisor > 1 else ""}`')
        # TODO: remove this hacky sack
        if self.dtype == 'uint32uint8array':
            return struct.pack('<IB', *value)

        # TODO: remove this hacky sack
        if type(value) == str:
            value = value.encode()

        pack_functions[DCTypes[self.dtype]](dg, value)
Ejemplo n.º 6
0
    def pack_field(self, dg, obj, field):
        if isinstance(field, ParameterField):
            try:
                if field.name:
                    val = getattr(obj, field.name)
                    field.pack_value(dg, val)
                    return
                elif isinstance(obj, collections.abc.Sequence):
                    val = obj[self.fields.index(field)]
                    field.pack_value(dg, val)
                    return
                else:
                    raise AttributeError
            except AttributeError:
                assert field.parameter.default is not None
                field.pack_default(dg)
                return
        elif isinstance(field, MolecularField):
            raise Exception
        else:

            if not len(field.parameters):
                return

            getter = field.name

            if getter[:3] == 'set':
                getter = ''.join(('get', getter[3:]))

            try:
                if field.name:
                    val = getattr(obj, getter)()

                    if len(field.parameters) == 1:
                        val = (val, )
                    field.pack_value(dg, val)
                    return

                elif isinstance(obj, collections.abc.Sequence):
                    val = obj[self.fields.index(field)]
                    field.pack_value(dg, val)
                    return
                else:
                    raise AttributeError
            except AttributeError as e:
                raise DCParseError(f'Could not find field: {field}, for object {obj}')
Ejemplo n.º 7
0
    def parameter(self, args):
        param_info = args.pop(0)
        identifier = None
        array_ranges = None
        ranges = []
        modulus = None
        divisor = 1

        if isinstance(param_info, Tree):
            if len(param_info.children) == 4:
                token, ranges, modulus, divisor = param_info.children
            else:
                token, ranges = param_info.children

            data_type = token

        elif isinstance(param_info, Token) and param_info.type == 'IDENTIFIER':
            token = param_info
            data_type, data_info = self.dcfile.resolve_type(token.value)
            if data_info is not None:
                ranges, modulus, divisor, array_ranges = data_info
        else:
            raise DCParseError('')

        if len(args) and isinstance(args[0], Token) and args[0].type == 'IDENTIFIER':
            identifier = args.pop(0).value

        current_array_ranges = None

        while args:
            v = args.pop(0)
            if isinstance(v, Tree):
                if v.data == 'array_range':
                    if current_array_ranges is None:
                        current_array_ranges = []
                    current_array_ranges.append(v.children)

        if array_ranges is None and current_array_ranges is not None:
            array_ranges = current_array_ranges
        elif current_array_ranges is not None:
            array_ranges = array_ranges + current_array_ranges

        if isinstance(data_type, Token):
            data_type = data_type.value

        if array_ranges is not None:
            return ArrayParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                  divisor=divisor, arange=array_ranges)
        elif token.type == 'IDENTIFIER':
            return StructParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                   divisor=divisor, arange=array_ranges)
        elif token.type == 'INT_TYPE':
            return IntParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                divisor=divisor)
        elif token.type == 'FLOAT_TYPE':
            return FloatParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                  divisor=divisor)
        elif token.type == 'CHAR_TYPE':
            return CharParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                 divisor=divisor)
        elif token.type == 'SIZED_TYPE':
            return SizedParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus,
                                  divisor=divisor)
        elif token.type == 'BUILTIN_ARRAY_TYPE':
            return ArrayParameter(dtype=data_type, identifier=identifier, vrange=ranges, modulus=modulus, divisor=divisor, arange=array_ranges)
Ejemplo n.º 8
0
 def pack_default(self, dg):
     if self.default is None:
         raise DCParseError('tried packing default for parameter without default')
     return self.pack_value(dg, self.default)