-
-
Notifications
You must be signed in to change notification settings - Fork 19
Add tagged-literal support #1101
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5860980
Add tagged-literal support
djblue dae291d
Add more tests
djblue 801ee73
Address PR comments
djblue ba0f152
Update src/basilisp/lang/tagged.py
djblue b8f59a8
Update src/basilisp/lang/tagged.py
djblue 41b4ec0
Update CHANGELOG
djblue a75d4ac
Run formatter
djblue 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
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,85 @@ | ||
| from typing import ( | ||
| Optional, | ||
| TypeVar, | ||
| Union, | ||
| ) | ||
|
|
||
| from typing_extensions import Unpack | ||
|
|
||
| from basilisp.lang.interfaces import ( | ||
| ILispObject, | ||
| ILookup, | ||
| ) | ||
|
|
||
| from basilisp.lang.keyword import keyword | ||
| from basilisp.lang.obj import PrintSettings, lrepr | ||
| from basilisp.lang.symbol import Symbol | ||
|
|
||
| K = TypeVar("K") | ||
| V = TypeVar("V") | ||
| T = Union[None, V, Symbol] | ||
|
|
||
| _TAG_KW = keyword("tag") | ||
| _FORM_KW = keyword("form") | ||
|
|
||
| class TaggedLiteral( | ||
| ILispObject, | ||
| ILookup[K, T], | ||
| ): | ||
| """Basilisp TaggedLiteral. https://clojure.org/reference/reader#tagged_literals | ||
| """ | ||
|
|
||
| __slots__ = ("_tag", "_form", "_hash") | ||
|
|
||
| def __init__( | ||
| self, tag: Symbol, form | ||
| ) -> None: | ||
| self._tag = tag | ||
| self._form = form | ||
| self._hash : Union[None, int] = None | ||
|
|
||
| @property | ||
| def tag(self) -> Symbol: | ||
| return self._tag | ||
|
|
||
| @property | ||
| def form(self): | ||
| return self._form | ||
|
|
||
| def __bool__(self): | ||
| return True | ||
|
|
||
| def __eq__(self, other): | ||
| if self is other: | ||
| return True | ||
| if not isinstance(other, TaggedLiteral): | ||
| return NotImplemented | ||
| return self._tag == other._tag and self._form == other._form | ||
|
|
||
| def __hash__(self): | ||
| if self._hash == None: | ||
djblue marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self._hash = hash((self._tag, self._form)) | ||
| return self._hash | ||
|
|
||
| def __getitem__(self, item): | ||
| return self.val_at(item) | ||
|
|
||
| def val_at(self, k: K, default: Optional[V] = None) -> T: | ||
| if k == _TAG_KW: | ||
| return self._tag | ||
| elif k == _FORM_KW: | ||
| return self._form | ||
| else: | ||
| return default | ||
|
|
||
| def _lrepr(self, **kwargs: Unpack[PrintSettings]) -> str: | ||
| return f"#{self._tag} {lrepr(self._form, **kwargs)}" | ||
|
|
||
| def tagged_literal( | ||
| tag: Symbol, form | ||
| ): | ||
| """Construct a data representation of a tagged literal from a | ||
| tag symbol and a form.""" | ||
| if not isinstance(tag, Symbol): | ||
| raise TypeError(f"tag must be a Symbol, not '{type(tag)}'") | ||
| return TaggedLiteral(tag, form) | ||
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,16 @@ | ||
| from basilisp.lang.symbol import symbol | ||
| from basilisp.lang.tagged import tagged_literal | ||
|
|
||
| def test_tagged_literal(): | ||
| tag = symbol("tag") | ||
| form = 1 | ||
| tagged = tagged_literal(tag, form) | ||
| assert tagged.tag == tag | ||
| assert tagged.form == form | ||
|
|
||
| def test_tagged_literal_str_and_repr(): | ||
| tag = symbol("tag") | ||
| form = 1 | ||
| tagged = tagged_literal(tag, form) | ||
| assert str(tagged) == "#tag 1" | ||
| assert repr(tagged) == "#tag 1" |
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 @@ | ||
| (ns tests.basilisp.test-tagged | ||
| (:require | ||
| [basilisp.test :refer [deftest is testing]])) | ||
|
|
||
| (deftest tagged-literal-test | ||
| (let [tag 'tag | ||
| form 1 | ||
| tagged (tagged-literal tag form)] | ||
| (testing "equality" | ||
| (is (= tagged tagged)) | ||
| (is (= tagged (tagged-literal tag form))) | ||
| (is (not= tagged (tagged-literal 'foo form))) | ||
| (is (not= tagged (tagged-literal tag 2)))) | ||
|
|
||
| (testing "accessors" | ||
| (is (= tag (:tag tagged))) | ||
| (is (= form (:form tagged))) | ||
| (is (nil? (:key tagged))) | ||
| (is (= ::default (:key tagged ::default)))) | ||
|
|
||
| (testing "predicate" | ||
| (is (true? (tagged-literal? tagged))) | ||
| (is (false? (tagged-literal? nil))) | ||
| (is (false? (tagged-literal? 0))) | ||
| (is (false? (tagged-literal? ::foo)))) | ||
|
|
||
| (testing "printing" | ||
| (is (= "#tag 1" (pr-str tagged))) | ||
| (is (= "#js []" (pr-str (tagged-literal 'js [])))) | ||
| (is (= "#js {}" (pr-str (tagged-literal 'js {}))))) | ||
|
|
||
| (testing "validation" | ||
| (is (thrown? TypeError (tagged-literal 1 1)))))) |
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.