コード例 #1
0
ファイル: dsl.py プロジェクト: geoffreycopin/langkit
    def create_enum_node_alternatives(mcs, enum_cls, enum_type):
        from langkit.expressions import Property

        enum_type.alternatives = enum_cls._alternatives
        enum_type.is_type_resolved = True
        enum_type._alternatives = []

        for alt in enum_cls._alternatives:
            alt_name = enum_cls._name + alt.name

            # Generate the derived class corresponding to this alternative
            fields = []
            if enum_cls._qualifier:
                prop = Property(alt.name.lower == 'present')
                prop.location = enum_cls._location
                fields.append(('as_bool', prop))

            alt_type = ASTNodeType(name=alt_name,
                                   location=None,
                                   doc='',
                                   base=enum_type,
                                   fields=fields)
            alt._type = alt_type
            alt._enum_node_cls = enum_cls

            # Make the alternative derived class accessible from the root
            # node for the enum.
            enum_type._alternatives.append(alt_type)
コード例 #2
0
ファイル: ocaml_api.py プロジェクト: yakobowski/langkit
    def get_parse_fields(self, node: ct.ASTNodeType) -> List[ct.Field]:
        """
        Return all the parse fields to be exposed as a field in record of node.

        :param node: The node type of which we want to get the parse fields.
        """
        return node.get_parse_fields(
            lambda x: not x.is_overriding and not x.abstract and not x.null)
コード例 #3
0
ファイル: dsl.py プロジェクト: GlancingMind/langkit
    def __new__(mcs, name, bases, dct):
        # Does this subclass come from this module? If so, it's not to be
        # considered as a DSLType per se.
        is_base = ((len(bases) == 1 and bases[0] in (object, BaseStruct))
                   or dct.pop('_ASTNodeList__is_astnode_list_cls', False))

        # Is this the root AST node type?
        is_root = not is_base and mcs.root_type is None

        if not is_base:
            mcs.process_subclass(name, bases, dct, is_root)

        cls = type.__new__(mcs, name, bases, dct)

        if is_root:
            mcs.root_type = cls

        if not is_base:
            mcs.astnode_types.append(cls)

            # Create the corresponding ASTNodeType subclass
            if cls._base is _ASTNodeList:
                # Only root list types are supposed to directly subclass
                # _ASTNodeList.
                element_type = cls._element_type._resolve()
                assert element_type
                astnode_type = element_type.list

            else:
                astnode_type = ASTNodeType(
                    cls._name,
                    cls._location,
                    cls._doc,
                    base=None if is_root else cls._base._resolve(),
                    fields=cls._fields,
                    env_spec=cls._env_spec,
                    annotations=cls._annotations,
                    is_token_node=cls._is_token_node,
                )

            astnode_type.dsl_decl = cls
            cls._type = astnode_type

        return cls
コード例 #4
0
ファイル: ocaml_api.py プロジェクト: setton/langkit
    def get_properties(self, node: ct.ASTNodeType) -> List[PropertyDef]:
        """
        Return the list of all properties that should be exposed to the user.

        :param ct.ASTNodeType node: The node for which we want to get the
            properties.
        """
        return [field
                for field in node.fields_with_accessors()
                if field.is_property]
コード例 #5
0
ファイル: dsl.py プロジェクト: geoffreycopin/langkit
    def process_subclass(mcs, name, bases, dct, is_root):
        from langkit.envs import EnvSpec

        location = extract_library_location()
        base = bases[0]
        is_list_type = issubclass(base, _ASTNodeList)
        is_root_list_type = base is _ASTNodeList

        node_ctx = Context('in {}'.format(name), location)

        with node_ctx:
            check_source_language(
                len(bases) == 1, 'ASTNode subclasses must have exactly one'
                ' base class')
            if mcs.root_type is not None:
                check_source_language(
                    base is not ASTNode,
                    'Only one class can derive from ASTNode (previous was:'
                    ' {})'.format(mcs.root_type.__name__))

            env_spec = dct.pop('env_spec', None)
            check_source_language(
                env_spec is None or isinstance(env_spec, EnvSpec),
                'Invalid environment specification: {}'.format(env_spec))

            annotations = dct.pop('annotations', None)

        # If this is a list type, determine the corresponding element type
        if is_list_type:
            element_type = (dct.pop('_element_type')
                            if is_root_list_type else base._element_type)
            allowed_field_types = PropertyDef
        else:
            element_type = None
            allowed_field_types = AbstractNodeData

        # Determine if this is a token node
        with node_ctx:
            is_token_node = dct.pop('token_node', None)
            check_source_language(
                is_token_node is None or isinstance(is_token_node, bool),
                'The "token_node" field, when present, must contain a boolean')

            # If "token_node" allocation is left to None, inherit it (default
            # is False).
            if is_token_node is None:
                is_token_node = bool(base._is_token_node)

            if is_token_node:
                allowed_field_types = (_UserField, PropertyDef)
            else:
                # Make sure that all derivations of a token node are token
                # nodes themselves.
                check_source_language(
                    not base._is_token_node,
                    '"token_node" annotation inconsistent with inherited AST'
                    ' node')

        # Handle enum nodes
        with node_ctx:
            # Forbid inheriting from an enum node
            check_source_language(
                not base._is_enum_node,
                'Inheriting from an enum node is forbidden.')

            # Determine if this is an enum node
            is_enum_node = dct.pop('enum_node', False)
            check_source_language(
                isinstance(is_enum_node, bool),
                'The "enum_node" field, when present, must contain a boolean')

            if is_enum_node:
                qualifier = dct.pop('qualifier', False)
                if qualifier:
                    alternatives = ['present', 'absent']
                else:
                    alternatives = dct.pop('alternatives', None)
                    check_source_language(alternatives is not None,
                                          'Missing "alternatives" field')
                    check_source_language(
                        isinstance(alternatives, list)
                        and all(isinstance(alt, str) for alt in alternatives),
                        'The "alternatives" field must contain a list of '
                        'strings')

                alts = [
                    _EnumNodeAlternative(names.Name.from_lower(alt))
                    for alt in alternatives
                ]

                allowed_field_types = (_UserField, PropertyDef)

        fields = ASTNode.collect_fields(name, location, dct,
                                        allowed_field_types)

        DSLType._import_base_type_info(name, location, dct)

        if is_enum_node:
            mcs.import_enum_node_attributes(dct, qualifier, alts, fields)

        dct['_fields'] = fields
        dct['_base'] = base
        dct['_env_spec'] = env_spec
        dct['_is_token_node'] = is_token_node
        dct['_is_enum_node'] = is_enum_node

        # Make sure subclasses don't inherit the "list_type" cache from their
        # base classes.
        dct['_list_type'] = None
        dct['_element_type'] = element_type
        dct['_annotations'] = annotations

        cls = type.__new__(mcs, name, bases, dct)

        mcs.astnode_types.append(cls)

        # Create the corresponding ASTNodeType subclass
        if cls._base is _ASTNodeList:
            # Only root list types are supposed to directly subclass
            # _ASTNodeList.
            element_type = cls._element_type._resolve()
            assert element_type
            astnode_type = element_type.list
        else:
            astnode_type = ASTNodeType(
                cls._name,
                cls._location,
                cls._doc,
                base=None if is_root else cls._base._resolve(),
                fields=cls._fields,
                env_spec=cls._env_spec,
                annotations=cls._annotations,

                # Only enum nodes are abstract at this point
                is_abstract=cls._is_enum_node,
                is_enum_node=cls._is_enum_node,
                is_bool_node=cls._is_enum_node and cls._qualifier,
                is_token_node=cls._is_token_node)

        astnode_type.dsl_decl = cls
        cls._type = astnode_type

        if is_enum_node:
            mcs.create_enum_node_alternatives(cls, astnode_type)

        return cls