-
-
Notifications
You must be signed in to change notification settings - Fork 6
Add support for c++ concepts #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
33a7434
feat: add support for c++ concepts
xXenvy 882bfd3
feat: add missing tests
xXenvy d4a221d
fix: failing tests
xXenvy 920ac62
fix: failing tests + pylint warnings
xXenvy 8316230
refactor: delete unnecessary overwrites
xXenvy 5cd1387
feat: the `requires` parsing + some cr suggestions
xXenvy 1e5e75b
fix: separate '(' and ')' tokens in requires parsing
xXenvy 56d1dd1
feat: add template and concept support for using
xXenvy d817525
fix: ignore pylint messages
xXenvy f633554
fix: invalid order of args in `template_arguments` when template using
xXenvy f161743
feat(tests): concept namespace and parameters tests
xXenvy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/devana/code_generation/printers/default/conceptprinter.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| from typing import Optional | ||
| from devana.code_generation.printers.icodeprinter import ICodePrinter | ||
| from devana.syntax_abstraction.conceptinfo import ConceptInfo | ||
| from devana.code_generation.printers.dispatcherinjectable import DispatcherInjectable | ||
| from devana.code_generation.printers.configuration import PrinterConfiguration | ||
| from devana.code_generation.printers.formatter import Formatter | ||
|
|
||
|
|
||
| class ConceptPrinter(ICodePrinter, DispatcherInjectable): | ||
| """Printer for concept declaration.""" | ||
|
|
||
| def print(self, source: ConceptInfo, config: Optional[PrinterConfiguration] = None, | ||
| context: Optional = None) -> str: | ||
| if config is None: | ||
| config = PrinterConfiguration() | ||
| formatter = Formatter(config) | ||
| if source.is_requirement: | ||
| parameters = [] | ||
| for p in source.parameters: | ||
| parameters.append(self.printer_dispatcher.print(p, config, source)) | ||
| parameters = ', '.join(parameters) | ||
| if len(parameters) > 0: | ||
| return f"{source.name}<{parameters}>" | ||
| return source.name | ||
| parameters = [] | ||
| for p in source.template.parameters: | ||
| parameters.append(self.printer_dispatcher.print(p, config, source)) | ||
| parameters = ', '.join(parameters) | ||
| template_prefix = f"template<{parameters}>" | ||
| formatter.print_line(template_prefix) | ||
|
|
||
| formatter.print_line(f"concept {source.name} = {source.body};") | ||
| return formatter.text |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 5 additions & 1 deletion
6
src/devana/code_generation/printers/default/templateparameterprinter.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| from __future__ import annotations | ||
| from typing import Optional, List, Any | ||
| from clang import cindex | ||
|
|
||
| from devana.syntax_abstraction.organizers.codecontainer import CodeContainer | ||
| from devana.syntax_abstraction.typeexpression import TypeExpression | ||
| from devana.syntax_abstraction.codepiece import CodePiece | ||
| from devana.syntax_abstraction.syntax import ISyntaxElement | ||
| from devana.utility.lazy import LazyNotInit, lazy_invoke | ||
| from devana.utility.init_params import init_params | ||
| from devana.utility.errors import ParserError | ||
|
|
||
|
|
||
| class ConceptInfo(CodeContainer): | ||
| """Represents a C++ concept, either as a full definition or as a requirement.""" | ||
|
|
||
| def __init__(self, cursor: Optional[cindex.Cursor] = None, parent: Optional[CodeContainer] = None): | ||
| super().__init__(cursor, parent) | ||
| if cursor is None: | ||
| from devana.syntax_abstraction.templateinfo import TemplateInfo # pylint: disable=import-outside-toplevel | ||
|
|
||
| self._name = "DefaultConcept" | ||
| self._body = "true" | ||
| self._template = TemplateInfo.from_params(parameters=[ | ||
| TemplateInfo.TemplateParameter.create_default() | ||
| ]) | ||
| self._parameters = [] | ||
| self._is_requirement = False | ||
| else: | ||
| if not self.is_cursor_valid(cursor): | ||
| raise ParserError(f"It is not a valid type cursor: {cursor.kind}.") | ||
| self._name = LazyNotInit | ||
| self._body = LazyNotInit | ||
| self._template = LazyNotInit | ||
| self._parameters = LazyNotInit | ||
| self._is_requirement = LazyNotInit | ||
|
|
||
| def __repr__(self): | ||
| return f"{type(self).__name__}:{self.name} ({super().__repr__()})" | ||
|
|
||
| @classmethod | ||
| def create_default(cls, parent: Optional = None) -> "ConceptInfo": | ||
| return cls(None, parent) | ||
|
|
||
| @classmethod | ||
| def from_cursor(cls, cursor: cindex.Cursor, parent: Optional = None) -> Optional["ConceptInfo"]: | ||
| if cls.is_cursor_valid(cursor): | ||
| return cls(cursor, parent) | ||
| return None | ||
|
|
||
| @classmethod | ||
| @init_params(skip={"parent"}) | ||
| def from_params( # pylint: disable=unused-argument | ||
| cls, | ||
| parent: Optional[ISyntaxElement] = None, | ||
| content: Optional[List[Any]] = None, | ||
| namespace: Optional[str] = None, | ||
| name: Optional[str] = None, | ||
| body: Optional[str] = None, | ||
| template: Optional[ISyntaxElement] = None, | ||
| parameters: Optional[List[TypeExpression]] = None, | ||
| is_requirement: Optional[bool] = None | ||
| ) -> "ConceptInfo": | ||
| return cls(None, parent) | ||
|
|
||
| @staticmethod | ||
| def is_cursor_valid(cursor: cindex.Cursor) -> bool: | ||
| return cursor.kind == cindex.CursorKind.CONCEPT_DECL | ||
|
|
||
| @property | ||
| @lazy_invoke | ||
| def name(self) -> str: | ||
| self._name = self._cursor.spelling | ||
| return self._name | ||
|
|
||
| @name.setter | ||
| def name(self, value) -> None: | ||
| self._name = value | ||
|
|
||
| @property | ||
| @lazy_invoke | ||
| def template(self) -> ISyntaxElement: | ||
| """Template associated with this concept.""" | ||
| from devana.syntax_abstraction.templateinfo import TemplateInfo # pylint: disable=import-outside-toplevel | ||
| self._template = TemplateInfo.from_cursor(self._cursor) | ||
| return self._template | ||
|
|
||
| @template.setter | ||
| def template(self, value: ISyntaxElement) -> None: | ||
| self._template = value | ||
|
|
||
| @property | ||
| @lazy_invoke | ||
| def body(self) -> str: | ||
| """The body of the concept, which defines its constraint expression.""" | ||
| self._body = "" | ||
| for child in self._cursor.get_children(): | ||
| if child.kind != cindex.CursorKind.TEMPLATE_TYPE_PARAMETER: | ||
| self._body = CodePiece(child).text | ||
| break | ||
| return self._body | ||
|
|
||
| @body.setter | ||
| def body(self, value: str) -> None: | ||
| self._body = value | ||
|
|
||
| @property | ||
| @lazy_invoke | ||
| def parameters(self) -> List[TypeExpression]: | ||
| """Retrieves the concept parameters '<...>'.""" | ||
| from devana.syntax_abstraction.templateinfo import TemplateInfo # pylint: disable=import-outside-toplevel | ||
| if not isinstance(self.parent, TemplateInfo.TemplateParameter): | ||
| return [] | ||
| # Probably without a cursor from the parent it will not be possible to extract it. | ||
| # I get a mental breakdown every time I see the number -1, when i want to extract parameters in the normal way. | ||
| # Fuck it for now. | ||
xXenvy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return [] | ||
|
|
||
| @parameters.setter | ||
| def parameters(self, value: List[TypeExpression]) -> None: | ||
| self._parameters = value | ||
|
|
||
| @property | ||
| @lazy_invoke | ||
| def is_requirement(self) -> bool: | ||
| """Determines whether this ConceptInfo instance is acting as a requirement.""" | ||
| from devana.syntax_abstraction.functioninfo import FunctionInfo # pylint: disable=import-outside-toplevel | ||
| from devana.syntax_abstraction.templateinfo import TemplateInfo # pylint: disable=import-outside-toplevel | ||
| self._is_requirement = isinstance( | ||
| self.parent, ( | ||
| TemplateInfo.TemplateParameter, | ||
| TemplateInfo, FunctionInfo | ||
| ) | ||
| ) | ||
| return self._is_requirement | ||
|
|
||
| @is_requirement.setter | ||
| def is_requirement(self, value: bool) -> None: | ||
| self._is_requirement = value | ||
|
|
||
| @property | ||
| def _content_types(self) -> List: | ||
| return [ConceptInfo] | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.