-
Notifications
You must be signed in to change notification settings - Fork 83
feat: 🧑💻 Check device literal port numbers at compile time #689
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
base: develop-pros-4
Are you sure you want to change the base?
Changes from all commits
0999dc2
9a792f0
af82fcd
6489fa4
bea9c44
dd8544a
64eb74d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| /** | ||
| * \file pros/detail.hpp | ||
| * | ||
| * Contains PROS internal functions used in port literal functions. | ||
| * | ||
| * This file should not be modified by users, since it gets replaced whenever | ||
| * a kernel upgrade occurs. | ||
| * | ||
| * Copyright (c) 2017-2024 Purdue University ACM SIGBots. | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| * | ||
| */ | ||
| #ifndef _PROS_DETAIL_HPP_ | ||
| #define _PROS_DETAIL_HPP_ | ||
|
|
||
| #include <array> | ||
| #include <charconv> | ||
| #include <cstdint> | ||
|
|
||
| namespace pros::detail { | ||
| template <char ...Chars> | ||
| consteval uint8_t parse_port() { | ||
| const std::array chars{Chars...}; | ||
| const char* str = chars.begin(); | ||
| int base = 10; | ||
| uint8_t port_num{0}; | ||
| if (chars.size() >= 2 && chars[0] == '0') { | ||
| str += 2; | ||
| // from_chars doesn't seem to handle hex/binary/octal prefixes, | ||
| // so we handle them ourselves | ||
|
Comment on lines
+32
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sucks lmao, good catch though
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out it does, I failed to read the docs lol. Fixed in bea9c44.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh thank god
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out I failed to read the docs doubly lol: from_chars does indeed NOT auto detect base womp womp
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lol? so what, we need to add back in the
ion098 marked this conversation as resolved.
|
||
| switch (chars[1]) { | ||
| case 'X': case 'x': | ||
| // hex literal | ||
| base = 16; | ||
|
Comment on lines
+36
to
+37
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does |
||
| break; | ||
| case 'B': case 'b': | ||
| // binary literal | ||
| base = 2; | ||
| break; | ||
| default: | ||
| // octal literal | ||
| str -= 1; | ||
| base = 8; | ||
| } | ||
| } | ||
| auto result = std::from_chars(str, chars.end(), port_num, base); | ||
| if (result.ptr != chars.end() || result.ec != std::errc{}) { | ||
| return 0; | ||
| } | ||
| return port_num; | ||
| } | ||
|
|
||
| template <char ...Chars> | ||
| consteval bool is_valid_port() { | ||
| auto port_num = parse_port<Chars...>(); | ||
| return port_num >= 1 && port_num <= 21; | ||
| } | ||
|
ion098 marked this conversation as resolved.
|
||
|
|
||
| // Tests: | ||
| static_assert(is_valid_port<'1'>() == true, "Kernel test failed"); | ||
| static_assert(is_valid_port<'0'>() == false, "Kernel test failed"); | ||
| // 0x16 = 22 | ||
| static_assert(is_valid_port<'0','x','1','6'>() == false, "Kernel test failed"); | ||
| // 0x15 = 21 | ||
| static_assert(is_valid_port<'0','x','1','5'>() == true, "Kernel test failed"); | ||
| // 025 = 21 | ||
| static_assert(is_valid_port<'0','2','5'>() == true, "Kernel test failed"); | ||
| // 0b1 = 1 | ||
| static_assert(is_valid_port<'0','b','1'>() == true, "Kernel test failed"); | ||
| // 0x1 = 1 | ||
| static_assert(is_valid_port<'0','x','1'>() == true, "Kernel test failed"); | ||
| static_assert(is_valid_port<'2','2'>() == false, "Kernel test failed"); | ||
|
|
||
| } | ||
|
|
||
| #endif // _PROS_DETAIL_HPP_ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| #include "pros/abstract_motor.hpp" | ||
| #include "pros/device.hpp" | ||
| #include "pros/motors.h" | ||
| #include "pros/detail.hpp" | ||
| #include "rtos.hpp" | ||
|
|
||
| namespace pros { | ||
|
|
@@ -2405,7 +2406,13 @@ namespace literals { | |
| * } | ||
| * \endcode | ||
| */ | ||
| const pros::Motor operator"" _mtr(const unsigned long long int m); | ||
| template <char... Cs> | ||
| const pros::Motor operator"" _mtr() { | ||
| static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!"); | ||
| constexpr int num = pros::detail::parse_port<Cs...>(); | ||
| return pros::Motor(num); | ||
| } | ||
|
|
||
| /** | ||
| * Constructs a reversed Motor from a literal ending in _rmtr | ||
| * | ||
|
|
@@ -2419,7 +2426,12 @@ const pros::Motor operator"" _mtr(const unsigned long long int m); | |
| * } | ||
| * \endcode | ||
| */ | ||
| const pros::Motor operator"" _rmtr(const unsigned long long int m); | ||
| template <char... Cs> | ||
| const pros::Motor operator"" _rmtr() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if theres a single pros project in the whole world that uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!"); | ||
| constexpr int num = pros::detail::parse_port<Cs...>(); | ||
| return pros::Motor(-num); | ||
| } | ||
| } // namespace literals | ||
| } // namespace v5 | ||
| } // namespace pros | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
|
|
||
| #include "pros/device.hpp" | ||
| #include "pros/rotation.h" | ||
| #include "pros/detail.hpp" | ||
|
|
||
| namespace pros { | ||
| inline namespace v5 { | ||
|
|
@@ -369,6 +370,23 @@ class Rotation : public Device { | |
| */ | ||
| friend std::ostream& operator<<(std::ostream& os, const pros::Rotation& rotation); | ||
|
|
||
| /** | ||
| * Returns a rotation sesnor that has the same port as the original, but reversed. | ||
| * | ||
| * This can only be used on a temporary object (such as a device literal). | ||
| * | ||
| * \b Example | ||
| * \code | ||
| * using namespace pros::literals; | ||
| * | ||
| * void opcontrol() { | ||
| * pros::Rotation rotation_sensor = -1_rot; | ||
| * printf("Reversed: %d \n", rotation_sensor.get_reversed()); | ||
| * } | ||
| * \endcode | ||
| */ | ||
| Rotation operator-() && { return Rotation(-this->get_port()); } | ||
|
Comment on lines
+373
to
+388
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why should this exist? can you not create negatives with the other user-defined literal operator? If you can, then this probably shouldnt exist
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see that its rvalue-this-qualified. still a little weird
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, not for rotation sensors. Both
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is necessary for rotation, its surely necessary for motors too?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hopefully its not necessary for either though lol
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im just confused why this doesnt work with the user-defined literal directly.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Motors have _rmtr so its not needed for motors, although adding this to motors might be a good idea for consistency
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh i see. yeah that sucks lmao. i think this should be added to motors as well if it has to exist. |
||
|
|
||
| ///@} | ||
| }; | ||
|
|
||
|
|
@@ -386,7 +404,12 @@ namespace literals { | |
| * } | ||
| * \endcode | ||
| */ | ||
| const pros::Rotation operator"" _rot(const unsigned long long int r); | ||
| template <char... Cs> | ||
| const pros::Rotation operator"" _rot() { | ||
| static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!"); | ||
| constexpr int num = pros::detail::parse_port<Cs...>(); | ||
| return pros::Rotation(num); | ||
| } | ||
| } // namespace literals | ||
| } // namespace v5 | ||
| } // namespace pros | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.