Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Analysis/include/Luau/Def.h
2727 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#pragma once
3
4
#include "Luau/NotNull.h"
5
#include "Luau/TypedAllocator.h"
6
#include "Luau/Variant.h"
7
#include "Luau/Location.h"
8
#include "Luau/Symbol.h"
9
#include <string>
10
#include <optional>
11
12
namespace Luau
13
{
14
15
struct Def;
16
using DefId = NotNull<const Def>;
17
struct AstLocal;
18
19
/**
20
* A cell is a "single-object" value.
21
*
22
* Leaky implementation note: sometimes "multiple-object" values, but none of which were interesting enough to warrant creating a phi node instead.
23
* That can happen because there's no point in creating a phi node that points to either resultant in `if math.random() > 0.5 then 5 else "hello"`.
24
* This might become of utmost importance if we wanted to do some backward reasoning, e.g. if `5` is taken, then `cond` must be `truthy`.
25
*/
26
struct Cell
27
{
28
bool subscripted = false;
29
};
30
31
/**
32
* A phi node is a union of cells.
33
*
34
* We need this because we're statically evaluating a program, and sometimes a place may be assigned with
35
* different cells, and when that happens, we need a special data type that merges in all the cells
36
* that will flow into that specific place. For example, consider this simple program:
37
*
38
* ```
39
* x-1
40
* if cond() then
41
* x-2 = 5
42
* else
43
* x-3 = "hello"
44
* end
45
* x-4 : {x-2, x-3}
46
* ```
47
*
48
* At x-4, we know for a fact statically that either `5` or `"hello"` can flow into the variable `x` after the branch, but
49
* we cannot make any definitive decisions about which one, so we just take in both.
50
*/
51
struct Phi
52
{
53
std::vector<DefId> operands;
54
};
55
56
/**
57
* We statically approximate a value at runtime using a symbolic value, which we call a Def.
58
*
59
* DataFlowGraphBuilder will allocate these defs as a stand-in for some Luau values, and bind them to places that
60
* can hold a Luau value, and then observes how those defs will commute as it statically evaluate the program.
61
*
62
* It must also be noted that defs are a cyclic graph, so it is not safe to recursively traverse into it expecting it to terminate.
63
*/
64
struct Def
65
{
66
using V = Variant<struct Cell, struct Phi>;
67
68
V v;
69
Symbol name;
70
Location location;
71
};
72
73
template<typename T>
74
const T* get(DefId def)
75
{
76
return get_if<T>(&def->v);
77
}
78
79
bool containsSubscriptedDefinition(DefId def);
80
void collectOperands(DefId def, std::vector<DefId>* operands);
81
82
struct DefArena
83
{
84
TypedAllocator<Def> allocator;
85
86
DefId freshCell(Symbol sym, Location location, bool subscripted = false);
87
DefId phi(DefId a, DefId b);
88
DefId phi(const std::vector<DefId>& defs);
89
};
90
91
} // namespace Luau
92
93