Sketch out Language a little bit. Still WIP.

This commit is contained in:
Alexander McCord 2024-05-26 13:11:38 -07:00
parent 18726c1ed5
commit d6f553a794
4 changed files with 90 additions and 3 deletions

View file

@ -57,7 +57,7 @@ private:
std::unordered_map<Id, EClass<L, typename N::Data>> classes;
/// The hashcons 𝐻 is a map from e-nodes to e-class ids.
std::unordered_map<L, Id> hashcons;
std::unordered_map<L, Id, typename L::Hash> hashcons;
};
} // namespace Luau::EqSat

View file

@ -1,12 +1,71 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include <algorithm>
#include <type_traits>
#include <utility>
namespace Luau::EqSat
{
struct Language
{
#define LUAU_EQSAT_ATOM(name, value) LUAU_EQSAT_ATOM_CUSTOM(name, #name, value)
#define LUAU_EQSAT_ATOM_CUSTOM(name, custom, value) \
struct name : public ::Luau::EqSat::Atom<name, value> \
{ \
static constexpr const char* tag = custom; \
}
template<typename B, typename T>
struct Atom
{
T value;
};
// `Language` is very similar to `Luau::Variant` with enough differences warranting a different type altogether.
//
// Firstly, where `Luau::Variant` uses an `int` to decide which type the variant currently holds, we use
// a `const char*` instead. We use the pointer address for tag checking, and the string buffer for stringification.
//
// Secondly, we need `Language` to have additional methods such as:
// - `children()` to get child operands,
// - `operator==` to decide equality, and
// - `hash()` function.
//
// And finally, each `T` in `Ts` have additional requirements which `Luau::Variant` doesn't need.
template<typename... Ts>
class Language
{
const char* tag;
char buffer[std::max({sizeof(Ts)...})];
public:
template<typename T>
Language(T&& t)
{
using TT = std::decay_t<T>;
static_assert(std::disjunction_v<std::is_same<TT, Ts>...>);
tag = T::tag;
new (&buffer) TT(std::forward<T>(t));
}
template<typename T>
const T* get() const
{
static_assert(std::disjunction_v<std::is_same<std::decay_t<T>, Ts>...>);
return tag == T::tag ? reinterpret_cast<const T*>(&buffer) : nullptr;
}
public:
struct Hash
{
size_t operator()(const Language<Ts...>& lang)
{
// TODO. Currently here so I can build and test this project.
return 0;
}
};
};
} // namespace Luau::EqSat

View file

@ -429,6 +429,8 @@ if(TARGET Luau.UnitTest)
tests/DiffAsserts.cpp
tests/DiffAsserts.h
tests/Differ.test.cpp
tests/EqSat.language.test.cpp
tests/EqSat.propositional.test.cpp
tests/Error.test.cpp
tests/Fixture.cpp
tests/Fixture.h

View file

@ -0,0 +1,26 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#include <doctest.h>
#include "Luau/Language.h"
LUAU_EQSAT_ATOM(Atom1, bool);
LUAU_EQSAT_ATOM(Atom2, bool);
using namespace Luau;
using Mini = EqSat::Language<Atom1, Atom2>;
TEST_SUITE_BEGIN("EqSatLanguage");
TEST_CASE("language_get_works")
{
Mini m{Atom1{true}};
const Atom1* atom = m.get<Atom1>();
REQUIRE(atom);
CHECK(atom->value);
CHECK(!m.get<Atom2>());
}
TEST_SUITE_END();