Skip to content

Commit

Permalink
Fix lex tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jeaye committed Feb 12, 2025
1 parent 9a96965 commit c6795d3
Show file tree
Hide file tree
Showing 8 changed files with 724 additions and 534 deletions.
6 changes: 5 additions & 1 deletion compiler+runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWith
list(APPEND jank_common_compiler_flags -DJANK_RELEASE)
endif()

if(jank_tests)
list(APPEND jank_common_compiler_flags -Werror -DJANK_TEST)
endif()

include(cmake/coverage.cmake)
include(cmake/analyze.cmake)
include(cmake/sanitization.cmake)
Expand Down Expand Up @@ -442,7 +446,7 @@ if(jank_tests)
test/cpp/jank/native_persistent_string.cpp
test/cpp/jank/util/string_builder.cpp
test/cpp/jank/read/lex.cpp
test/cpp/jank/read/parse.cpp
#test/cpp/jank/read/parse.cpp
test/cpp/jank/analyze/box.cpp
test/cpp/jank/runtime/detail/native_persistent_list.cpp
test/cpp/jank/runtime/obj/persistent_string.cpp
Expand Down
11 changes: 11 additions & 0 deletions compiler+runtime/include/cpp/jank/read/lex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ namespace jank::read::lex
native_bool const);
token(movable_position const &s, movable_position const &e, token_kind const k, ratio const);

#ifdef JANK_TEST
/* These assume everything is on one line; very useful for tests, but not elsewhere. */
token(size_t offset, size_t width, token_kind const k);
token(size_t offset, size_t width, token_kind const k, native_integer const);
token(size_t offset, size_t width, token_kind const k, native_real const);
token(size_t offset, size_t width, token_kind const k, native_persistent_string_view const);
token(size_t offset, size_t width, token_kind const k, char const * const);
token(size_t offset, size_t width, token_kind const k, native_bool const);
token(size_t offset, size_t width, token_kind const k, ratio const);
#endif

native_bool operator==(token const &rhs) const;
native_bool operator!=(token const &rhs) const;

Expand Down
20 changes: 18 additions & 2 deletions compiler+runtime/include/cpp/jank/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <boost/variant.hpp>

#include <jank/option.hpp>
#include <jank/util/type_name.hpp>

namespace jank
{
Expand Down Expand Up @@ -346,9 +347,24 @@ namespace jank
{
if(r.is_ok())
{
return os << "ok(" << boost::get<R>(r.data) << ")";
if constexpr(requires(R t) { os << t; })
{
return os << "ok(" << boost::get<R>(r.data) << ")";
}
else
{
return os << "ok(" << util::type_name<R>() << ")";
}
}

if constexpr(requires(E t) { os << t; })
{
return os << "err(" << boost::get<E>(r.data) << ")";
}
else
{
return os << "err(" << util::type_name<E>() << ")";
}
return os << "err(" << boost::get<E>(r.data) << ")";
}

template <typename R>
Expand Down
6 changes: 0 additions & 6 deletions compiler+runtime/include/cpp/jank/runtime/native_box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,4 @@ namespace jank::runtime
}
return ret;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, native_box<T> const &o)
{
return os << "box(" << o.data << ")";
}
}
75 changes: 75 additions & 0 deletions compiler+runtime/include/cpp/jank/util/type_name.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <string_view>
#include <array>
#include <utility>

namespace jank::util
{
template <std::size_t... Idxs>
constexpr auto substring_as_array(std::string_view const str, std::index_sequence<Idxs...> const)
{
return std::array{ str[Idxs]... };
}

template <typename T>
constexpr auto type_name_array()
{
/* Based on using this code: https://gist.github.com/jeaye/7e11ee6e78164f41a0342c166d294dd0 */
#if defined(__clang__)
/* void foo() [T = std::basic_string<char>] */
constexpr auto prefix{ std::string_view{ "[T = " } };
constexpr auto suffix{ std::string_view{ "]" } };
constexpr auto function{ std::string_view{ __PRETTY_FUNCTION__ } };
#elif defined(__GNUC__)
/* void foo() [with T = std::__cxx11::basic_string<char>] */
constexpr auto prefix{ std::string_view{ "with T = " } };
constexpr auto suffix{ std::string_view{ "]" } };
constexpr auto function{ std::string_view{ __PRETTY_FUNCTION__ } };
#elif defined(_MSC_VER)
/* void __cdecl foo<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >>(void) */
constexpr auto prefix{ std::string_view{ "type_name_array<" } };
constexpr auto suffix{ std::string_view{ ">(void)" } };
constexpr auto function{ std::string_view{ __FUNCSIG__ } };
#else
#error Unsupported compiler
#endif

constexpr auto start{ function.find(prefix) + prefix.size() };
constexpr auto end{ function.rfind(suffix) };

static_assert(start < end);

constexpr auto name{ function.substr(start, (end - start)) };
return substring_as_array(name, std::make_index_sequence<name.size()>{});
}

template <typename T>
struct type_name_holder
{
static constexpr auto value{ type_name_array<T>() };
};

/* This is incredibly hacky. C++ doesn't offer a standard way to get an unmangled type from
* an arbitrary type. To work around this, we use the __PRETTY_FUNCTION__ macro, which
* contains the current function we're in, including the template parameters. We then
* instantiate a template using the type we want, check the __PRETTY_FUNCTION__ macro,
* and parse out the type name. For example:
*
* void foo() [T = std::basic_string<char>]
*
* But there's a catch. Every compiler formats the text in their own way. So we need
* special handling, depending on the compiler, to know how to pull out the type from
* the string.
*
* With that done, we just do some template work to turn the string literal into a
* constexpr static variable to which we can have a string_view. Entirely at compile-time.
*
* Just do type_name<T>() and there's your string_view. */
template <typename T>
constexpr std::string_view type_name()
{
constexpr auto &value{ type_name_holder<T>::value };
return { value.data(), value.size() };
}
}
75 changes: 68 additions & 7 deletions compiler+runtime/src/cpp/jank/read/lex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ namespace jank::read::lex
{
}

#ifdef JANK_TEST
token::token(movable_position const &s,
movable_position const &e,
token_kind const k,
Expand All @@ -118,6 +119,65 @@ namespace jank::read::lex
{
}

token::token(size_t const offset, size_t const width, token_kind const k)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
{
}

token::token(size_t const offset, size_t const width, token_kind const k, native_integer const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}

token::token(size_t const offset, size_t const width, token_kind const k, native_real const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}

token::token(size_t const offset,
size_t const width,
token_kind const k,
native_persistent_string_view const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}

token::token(size_t const offset, size_t const width, token_kind const k, char const * const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}

token::token(size_t const offset, size_t const width, token_kind const k, native_bool const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}

token::token(size_t const offset, size_t const width, token_kind const k, ratio const d)
: start{ offset, 1, offset + 1 }
, end{ offset + width, 1, offset + width + 1 }
, kind{ k }
, data{ d }
{
}
#endif

struct codepoint
{
char32_t character{};
Expand Down Expand Up @@ -421,25 +481,25 @@ namespace jank::read::lex
{
case '(':
require_space = false;
return ok(token{ pos++, token_kind::open_paren });
return ok(token{ token_start, ++pos, token_kind::open_paren });
case ')':
require_space = false;
return ok(token{ pos++, token_kind::close_paren });
return ok(token{ token_start, ++pos, token_kind::close_paren });
case '[':
require_space = false;
return ok(token{ pos++, token_kind::open_square_bracket });
return ok(token{ token_start, ++pos, token_kind::open_square_bracket });
case ']':
require_space = false;
return ok(token{ pos++, token_kind::close_square_bracket });
return ok(token{ token_start, ++pos, token_kind::close_square_bracket });
case '{':
require_space = false;
return ok(token{ pos++, token_kind::open_curly_bracket });
return ok(token{ token_start, ++pos, token_kind::open_curly_bracket });
case '}':
require_space = false;
return ok(token{ pos++, token_kind::close_curly_bracket });
return ok(token{ token_start, ++pos, token_kind::close_curly_bracket });
case '\'':
require_space = false;
return ok(token{ pos++, token_kind::single_quote });
return ok(token{ token_start, ++pos, token_kind::single_quote });
case '\\':
{
require_space = false;
Expand Down Expand Up @@ -866,6 +926,7 @@ namespace jank::read::lex
case '<':
case '>':
case '%':
case '.':
{
auto &&e(check_whitespace(found_space));
if(e.is_some())
Expand Down
Loading

0 comments on commit c6795d3

Please sign in to comment.