Skip to content

Commit

Permalink
Documentation for literals
Browse files Browse the repository at this point in the history
Give them more clear names, and add longer explanations for
each one with examples.
  • Loading branch information
danakj committed Dec 20, 2023
1 parent 5b2da1a commit 7930a3f
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 44 deletions.
4 changes: 4 additions & 0 deletions subdoc/gen_tests/subdoc-test-style.css
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ pre > code span.punct {
}
code {
color: rgb(124, 216, 204);
white-space: nowrap;
}
pre code {
white-space: pre;
}
.description h1, .description h2 {
font-size: 100%;
Expand Down
13 changes: 10 additions & 3 deletions subdoc/lib/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ struct FunctionOverload {
bool is_deleted = false;
// Used to look for uniqueness to avoid adding each forward decl and get
// multiple overloads of the same function.
std::string signature;
std::string signature_key;

// TODO: `noexcept` stuff from FunctionDecl::getExceptionSpecType().
};
Expand Down Expand Up @@ -253,7 +253,8 @@ struct AliasElement : public TypeElement {
struct FunctionElement : public CommentElement {
explicit FunctionElement(sus::Vec<Namespace> containing_namespaces,
Comment comment, std::string name,
std::string signature, bool is_operator,
std::string signature_name,
std::string signature_key, bool is_operator,
LinkedType return_type,
sus::Option<RequiresConstraints> constraints,
sus::Vec<std::string> template_params,
Expand All @@ -263,6 +264,7 @@ struct FunctionElement : public CommentElement {
sus::Vec<std::string> record_path, u32 sort_key)
: CommentElement(sus::move(containing_namespaces), sus::move(comment),
sus::move(name), sort_key),
signature_name(sus::move(signature_name)),
is_operator(is_operator),
overload_set(sus::move(overload_set)),
record_path(sus::move(record_path)) {
Expand All @@ -273,10 +275,15 @@ struct FunctionElement : public CommentElement {
.constraints = sus::move(constraints),
.template_params = sus::move(template_params),
.is_deleted = is_deleted,
.signature = sus::move(signature),
.signature_key = sus::move(signature_key),
});
}

/// Typically the same as the function `name`, but whereas the former is used
/// in links and titles for the function, this name is used in the
/// representation of the function signature. It differs for UDLs, for
/// example, which have a more descriptive display name.
std::string signature_name;
bool is_operator;
sus::Vec<FunctionOverload> overloads;
sus::Option<std::string> overload_set;
Expand Down
2 changes: 1 addition & 1 deletion subdoc/lib/gen/generate_function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ sus::Result<void, MarkdownToHtmlError> generate_function(
auto name_anchor = signature_div.open_a();
name_anchor.add_href("#");
name_anchor.add_class("function-name");
name_anchor.write_text(element.name);
name_anchor.write_text(element.signature_name);
}
generate_function_params(signature_div, overload);
// This is generating a function that is not a method, so there's always
Expand Down
19 changes: 14 additions & 5 deletions subdoc/lib/visit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1127,8 +1127,7 @@ class Visitor : public clang::RecursiveASTVisitor<Visitor> {
auto* fdecl = clang::cast<clang::FunctionDecl>(decl->getFriendDecl());
// Friend forward declarations are not visited, they would create an
// overload which does not actually exist.
if (fdecl->getDefinition() != fdecl)
return true;
if (fdecl->getDefinition() != fdecl) return true;

if (should_skip_decl(cx_, fdecl)) return true;

Expand Down Expand Up @@ -1193,7 +1192,7 @@ class Visitor : public clang::RecursiveASTVisitor<Visitor> {
constraints = collect_function_constraints(decl, preprocessor_);
}

std::string function_name = [&] {
std::string signature_name = [&] {
if (auto* mdecl = clang::dyn_cast<clang::CXXConstructorDecl>(decl)) {
return mdecl->getThisType()
->getPointeeType()
Expand All @@ -1209,6 +1208,14 @@ class Visitor : public clang::RecursiveASTVisitor<Visitor> {
return decl->getNameAsString();
}
}();
std::string function_name = [&] {
if (auto* lit = decl->getLiteralIdentifier()) {
// User-defined literals are displayed... less literally.
return std::string(lit->getName()) + std::string(" literal");
} else {
return signature_name;
}
}();

// Make a copy before moving `comment` to the contructor argument.
sus::Option<std::string> overload_set =
Expand Down Expand Up @@ -1265,7 +1272,8 @@ class Visitor : public clang::RecursiveASTVisitor<Visitor> {
FunctionId db_key = key_for_function(decl, overload_set);
auto fe = FunctionElement(
iter_namespace_path(decl).collect_vec(), sus::move(comment),
sus::move(function_name), sus::move(signature),
sus::move(function_name), sus::move(signature_name),
sus::move(signature),
decl->isOverloadedOperator() || decl->getLiteralIdentifier() != nullptr,
sus::move(linked_return_type), sus::move(constraints),
sus::move(template_params), decl->isDeleted(), sus::move(params),
Expand Down Expand Up @@ -1379,7 +1387,8 @@ class Visitor : public clang::RecursiveASTVisitor<Visitor> {

bool exists = db_map.at(key).overloads.iter().any(
[&db_element](const FunctionOverload& overload) {
return overload.signature == db_element.overloads[0u].signature;
return overload.signature_key ==
db_element.overloads[0u].signature_key;
});
if (!exists)
db_map.at(key).overloads.push(sus::move(db_element.overloads[0u]));
Expand Down
67 changes: 34 additions & 33 deletions sus/num/__private/literals.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
#pragma once

#if _MSC_VER
#include "sus/assertions/check.h"
# include "sus/assertions/check.h"
# include "sus/num/cast.h"
#endif

#if _MSC_VER && !defined(__clang__)
/// Literal integer value.
#define _sus__integer_literal(Name, T) \
/* A `constexpr` workaround for MSVC bug that doesn't constant-evaluate \
# define _sus__integer_literal(Name, T) \
/* A `constexpr` workaround for MSVC bug that doesn't constant-evaluate \
* user-defined literals in all cases: \
* https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 \
* \
Expand All @@ -34,25 +35,25 @@
* However that triggers a different MSVC bug when used with any \
* unary/binary operator in a templated function: \
* https://developercommunity.visualstudio.com/t/MSVC-Compiler-bug-with:-numeric-literal/10108160 \
*/ \
T inline constexpr operator""_##Name(unsigned long long val) noexcept { \
sus_check(val <= static_cast<unsigned long long>(T::MAX_PRIMITIVE)); \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
*/ \
T inline constexpr operator""_##Name(unsigned long long val) noexcept { \
sus_check(val <= static_cast<unsigned long long>(T::MAX_PRIMITIVE)); \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
#else
/// Literal integer value.
#define _sus__integer_literal(Name, T) \
T inline consteval operator""_##Name(unsigned long long val) { \
if (val > static_cast<unsigned long long>(T::MAX_PRIMITIVE)) \
throw "Integer literal out of bounds for ##T##"; \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
# define _sus__integer_literal(Name, T) \
T inline consteval operator""_##Name(unsigned long long val) { \
if (val > static_cast<unsigned long long>(T::MAX_PRIMITIVE)) \
throw "Integer literal out of bounds for ##T##"; \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
#endif

#if _MSC_VER
/// Literal float value.
#define _sus__float_literal(Name, T) \
/* A `constexpr` workaround for MSVC bug that doesn't constant-evaluate \
# define _sus__float_literal(Name, T) \
/* A `constexpr` workaround for MSVC bug that doesn't constant-evaluate \
* user-defined literals in all cases: \
* https://developercommunity.visualstudio.com/t/User-defined-literals-not-constant-expre/10108165 \
* \
Expand All @@ -63,24 +64,24 @@
* However that triggers a different MSVC bug when used with any \
* unary/binary operator in a templated function: \
* https://developercommunity.visualstudio.com/t/MSVC-Compiler-bug-with:-numeric-literal/10108160 \
*/ \
T inline constexpr operator""_##Name(long double val) noexcept { \
sus_check(val <= static_cast<long double>(T::MAX_PRIMITIVE)); \
return T(static_cast<decltype(T::primitive_value)>(val)); \
} \
T inline constexpr operator""_##Name(unsigned long long val) noexcept { \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
*/ \
T inline constexpr operator""_##Name(long double val) noexcept { \
sus_check(val <= static_cast<long double>(T::MAX_PRIMITIVE)); \
return T(static_cast<decltype(T::primitive_value)>(val)); \
} \
T inline constexpr operator""_##Name(unsigned long long val) noexcept { \
return T(::sus::cast<decltype(T::primitive_value)>(val)); \
}

#else
/// Literal float value.
#define _sus__float_literal(Name, T) \
T inline consteval operator""_##Name(long double val) { \
if (val > static_cast<long double>(T::MAX_PRIMITIVE)) \
throw "Float literal out of bounds for ##T##"; \
return T(static_cast<decltype(T::primitive_value)>(val)); \
} \
T inline consteval operator""_##Name(unsigned long long val) { \
return T(static_cast<decltype(T::primitive_value)>(val)); \
}
# define _sus__float_literal(Name, T) \
T inline consteval operator""_##Name(long double val) { \
if (val > static_cast<long double>(T::MAX_PRIMITIVE)) \
throw "Float literal out of bounds for ##T##"; \
return T(static_cast<decltype(T::primitive_value)>(val)); \
} \
T inline consteval operator""_##Name(unsigned long long val) { \
return T(::sus::cast<decltype(T::primitive_value)>(val)); \
}
#endif
28 changes: 28 additions & 0 deletions sus/num/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,36 @@ struct [[_sus_trivial_abi]] f64 final {
} // namespace sus::num

/// For writing [`f32`]($sus::num::f32) literals.
///
/// Floating point literals qualified with `f` are also 32 bits large, but the
/// `_f32` suffix forces a safe numeric type instead of a primitive value when
/// this is needed (such as for templates or member function access).
///
/// Integer values that are not representable by [`f32`]($sus::num::f32) will
/// converted by the same rules as for [`Cast`]($sus::construct::Cast).
/// Floating point values out of range for [`f32`]($sus::num::f32) will fail to
/// compile.
///
/// # Examples
/// ```
/// auto i = 123_f32 - (5_f32).abs();
/// sus_check(i == 118_f32);
/// ```
_sus__float_literal(f32, ::sus::num::f32);
/// For writing [`f64`]($sus::num::f64) literals.
///
/// Floating point literals without a qualifier are also 64 bits large, but the
/// `_f64` suffix forces a safe numeric type instead of a primitive value when
/// this is needed (such as for templates or member function access).
///
/// Integer values that are not representable by [`f64`]($sus::num::f64) will
/// converted by the same rules as for [`Cast`]($sus::construct::Cast).
///
/// # Examples
/// ```
/// auto i = 123_f64- (5_f64).abs();
/// sus_check(i == 118_f64);
/// ```
_sus__float_literal(f64, ::sus::num::f64);

// Promote floating point types into the `sus` namespace.
Expand Down
66 changes: 66 additions & 0 deletions sus/num/signed_integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,80 @@ constexpr inline isize operator>>(isize l, U r) noexcept = delete;
} // namespace sus::num

/// For writing [`i8`]($sus::num::i8) literals.
///
/// Un-qualified integer literals are 32 bits large (the size of `int`)
/// unless a literal suffix modifies them, such as with `_i8` which creates
/// an 8-bit value.
///
/// Values out of range for [`i8`]($sus::num::i8) will fail to compile.
///
/// # Examples
/// ```
/// auto i = 123_i8 - (5_i8).abs();
/// sus_check(i == 118_i8);
/// ```
_sus__integer_literal(i8, ::sus::num::i8);
/// For writing [`i16`]($sus::num::i16) literals.
///
/// Un-qualified integer literals are 32 bits large (the size of `int`)
/// unless a literal suffix modifies them, such as with `_i16` which creates
/// an 16-bit value.
///
/// Values out of range for [`i16`]($sus::num::i16) will fail to compile.
///
/// # Examples
/// ```
/// auto i = 123_i16 - (5_i16).abs();
/// sus_check(i == 118_i16);
/// ```
_sus__integer_literal(i16, ::sus::num::i16);
/// For writing [`i32`]($sus::num::i32) literals.
///
/// Un-qualified integer literals are 32 bits large (the size of `int`), unless
/// a literal suffix modifies them. The `_i32` suffix creates an 32-bit value
/// which is the same as not adding a suffix at all, except that it forces a
/// safe numeric type instead of a primitive value when this is needed (such as
/// for templates or member function access).
///
/// Values out of range for [`i32`]($sus::num::i32) will fail to compile.
///
/// # Examples
/// ```
/// auto i = 123_i32 - (5_i32).abs();
/// sus_check(i == 118_i32);
/// ```
_sus__integer_literal(i32, ::sus::num::i32);
/// For writing [`i64`]($sus::num::i64) literals.
///
/// Un-qualified integer literals are 32 bits large (the size of `int`), unless
/// a literal suffix modifies them, such as with `_i64` which creates a 64-bit
/// value. On Windows, this is the same as the `l` suffix (which makes a
/// `long`) but is platform agnostic, and forces a safe numeric type instead of
/// a primitive value when this is needed (such as for templates or member
/// function access).
///
/// Values out of range for [`i64`]($sus::num::i64) will fail to compile.
///
/// # Examples
/// ```
/// auto i = 123_i64 - (5_i64).abs();
/// sus_check(i == 118_i64);
/// ```
_sus__integer_literal(i64, ::sus::num::i64);
/// For writing [`isize`]($sus::num::isize) literals.
///
/// Un-qualified integer literals are 32 bits large (the size of `int`), unless
/// a literal suffix modifies them, such as with `_isize` which creates an
/// address-sized value. This is 32 bits for 32-bit targets and 64 bits for
/// 64-bit targets.
///
/// Values out of range for [`isize`]($sus::num::isize) will fail to compile.
///
/// # Examples
/// ```
/// auto i = 123_isize - (5_isize).abs();
/// sus_check(i == 118_isize);
/// ```
_sus__integer_literal(isize, ::sus::num::isize);

// Promote signed integer types into the `sus` namespace.
Expand Down
Loading

0 comments on commit 7930a3f

Please sign in to comment.