mirror of
https://github.com/luau-lang/luau.git
synced 2024-12-14 06:00:39 +00:00
74c532053f
New Solver * New algorithm for inferring the types of locals that have no annotations. This algorithm is very conservative by default, but is augmented with some control flow awareness to handle most common scenarios. * Fix bugs in type inference of tables * Improve performance of by switching out standard C++ containers for `DenseHashMap` * Infrastructure to support clearer error messages in strict mode Native Code Generation * Fix a lowering issue with buffer.writeu8 and 0x80-0xff values: A constant argument wasn't truncated to the target type range and that causes an assertion failure in `build.mov`. * Store full lightuserdata value in loop iteration protocol lowering * Add analysis to compute function bytecode distribution * This includes a class to analyze the bytecode operator distribution per function and a CLI tool that produces a JSON report. See the new cmake target `Luau.Bytecode.CLI` --------- Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
171 lines
3.7 KiB
C++
171 lines
3.7 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
#pragma once
|
|
|
|
#include "Luau/DenseHash.h"
|
|
|
|
namespace Luau
|
|
{
|
|
|
|
template<typename T>
|
|
using SetHashDefault = std::conditional_t<std::is_pointer_v<T>, DenseHashPointer, std::hash<T>>;
|
|
|
|
// This is an implementation of `unordered_set` using `DenseHashMap<T, bool>` to support erasure.
|
|
// This lets us work around `DenseHashSet` limitations and get a more traditional set interface.
|
|
template<typename T, typename Hash = SetHashDefault<T>>
|
|
class Set
|
|
{
|
|
private:
|
|
using Impl = DenseHashMap<T, bool, Hash>;
|
|
Impl mapping;
|
|
size_t entryCount = 0;
|
|
|
|
public:
|
|
class const_iterator;
|
|
using iterator = const_iterator;
|
|
|
|
Set(const T& empty_key)
|
|
: mapping{empty_key}
|
|
{
|
|
}
|
|
|
|
bool insert(const T& element)
|
|
{
|
|
bool& entry = mapping[element];
|
|
bool fresh = !entry;
|
|
|
|
if (fresh)
|
|
{
|
|
entry = true;
|
|
entryCount++;
|
|
}
|
|
|
|
return fresh;
|
|
}
|
|
|
|
template<class Iterator>
|
|
void insert(Iterator begin, Iterator end)
|
|
{
|
|
for (Iterator it = begin; it != end; ++it)
|
|
insert(*it);
|
|
}
|
|
|
|
void erase(const T& element)
|
|
{
|
|
bool& entry = mapping[element];
|
|
|
|
if (entry)
|
|
{
|
|
entry = false;
|
|
entryCount--;
|
|
}
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
mapping.clear();
|
|
entryCount = 0;
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return entryCount;
|
|
}
|
|
|
|
bool empty() const
|
|
{
|
|
return entryCount == 0;
|
|
}
|
|
|
|
size_t count(const T& element) const
|
|
{
|
|
const bool* entry = mapping.find(element);
|
|
return (entry && *entry) ? 1 : 0;
|
|
}
|
|
|
|
bool contains(const T& element) const
|
|
{
|
|
return count(element) != 0;
|
|
}
|
|
|
|
const_iterator begin() const
|
|
{
|
|
return const_iterator(mapping.begin(), mapping.end());
|
|
}
|
|
|
|
const_iterator end() const
|
|
{
|
|
return const_iterator(mapping.end(), mapping.end());
|
|
}
|
|
|
|
bool operator==(const Set<T>& there) const
|
|
{
|
|
// if the sets are unequal sizes, then they cannot possibly be equal.
|
|
if (size() != there.size())
|
|
return false;
|
|
|
|
// otherwise, we'll need to check that every element we have here is in `there`.
|
|
for (auto [elem, present] : mapping)
|
|
{
|
|
// if it's not, we'll return `false`
|
|
if (present && there.contains(elem))
|
|
return false;
|
|
}
|
|
|
|
// otherwise, we've proven the two equal!
|
|
return true;
|
|
}
|
|
|
|
class const_iterator
|
|
{
|
|
public:
|
|
const_iterator(typename Impl::const_iterator impl, typename Impl::const_iterator end)
|
|
: impl(impl)
|
|
, end(end)
|
|
{}
|
|
|
|
const T& operator*() const
|
|
{
|
|
return impl->first;
|
|
}
|
|
|
|
const T* operator->() const
|
|
{
|
|
return &impl->first;
|
|
}
|
|
|
|
|
|
bool operator==(const const_iterator& other) const
|
|
{
|
|
return impl == other.impl;
|
|
}
|
|
|
|
bool operator!=(const const_iterator& other) const
|
|
{
|
|
return impl != other.impl;
|
|
}
|
|
|
|
|
|
const_iterator& operator++()
|
|
{
|
|
do
|
|
{
|
|
impl++;
|
|
} while (impl != end && impl->second == false);
|
|
// keep iterating past pairs where the value is `false`
|
|
|
|
return *this;
|
|
}
|
|
|
|
const_iterator operator++(int)
|
|
{
|
|
const_iterator res = *this;
|
|
++*this;
|
|
return res;
|
|
}
|
|
private:
|
|
typename Impl::const_iterator impl;
|
|
typename Impl::const_iterator end;
|
|
};
|
|
};
|
|
|
|
} // namespace Luau
|