Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Compiler/src/ValueTracking.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "ValueTracking.h"
3
4
#include "Luau/Lexer.h"
5
6
namespace Luau
7
{
8
namespace Compile
9
{
10
11
struct ValueVisitor : AstVisitor
12
{
13
DenseHashMap<AstName, Global>& globals;
14
DenseHashMap<AstLocal*, Variable>& variables;
15
16
ValueVisitor(DenseHashMap<AstName, Global>& globals, DenseHashMap<AstLocal*, Variable>& variables)
17
: globals(globals)
18
, variables(variables)
19
{
20
}
21
22
void assign(AstExpr* var)
23
{
24
if (AstExprLocal* lv = var->as<AstExprLocal>())
25
{
26
variables[lv->local].written = true;
27
}
28
else if (AstExprGlobal* gv = var->as<AstExprGlobal>())
29
{
30
globals[gv->name] = Global::Written;
31
}
32
else
33
{
34
// we need to be able to track assignments in all expressions, including crazy ones like t[function() t = nil end] = 5
35
var->visit(this);
36
}
37
}
38
39
bool visit(AstStatLocal* node) override
40
{
41
for (size_t i = 0; i < node->vars.size && i < node->values.size; ++i)
42
variables[node->vars.data[i]].init = node->values.data[i];
43
44
for (size_t i = node->values.size; i < node->vars.size; ++i)
45
variables[node->vars.data[i]].init = nullptr;
46
47
return true;
48
}
49
50
bool visit(AstStatAssign* node) override
51
{
52
for (size_t i = 0; i < node->vars.size; ++i)
53
assign(node->vars.data[i]);
54
55
for (size_t i = 0; i < node->values.size; ++i)
56
node->values.data[i]->visit(this);
57
58
return false;
59
}
60
61
bool visit(AstStatCompoundAssign* node) override
62
{
63
assign(node->var);
64
node->value->visit(this);
65
66
return false;
67
}
68
69
bool visit(AstStatLocalFunction* node) override
70
{
71
variables[node->name].init = node->func;
72
73
return true;
74
}
75
76
bool visit(AstStatFunction* node) override
77
{
78
assign(node->name);
79
node->func->visit(this);
80
81
return false;
82
}
83
84
bool visit(AstExprFunction* node) override
85
{
86
for (AstLocal* arg : node->args)
87
variables[arg].init = nullptr;
88
89
return true;
90
}
91
};
92
93
void assignMutable(DenseHashMap<AstName, Global>& globals, const AstNameTable& names, const char* const* mutableGlobals)
94
{
95
if (AstName name = names.get("_G"); name.value)
96
globals[name] = Global::Mutable;
97
98
if (mutableGlobals)
99
for (const char* const* ptr = mutableGlobals; *ptr; ++ptr)
100
if (AstName name = names.get(*ptr); name.value)
101
globals[name] = Global::Mutable;
102
}
103
104
void trackValues(DenseHashMap<AstName, Global>& globals, DenseHashMap<AstLocal*, Variable>& variables, AstNode* root)
105
{
106
ValueVisitor visitor{globals, variables};
107
root->visit(&visitor);
108
}
109
110
} // namespace Compile
111
} // namespace Luau
112
113