@@ -9,59 +9,130 @@ enum class Scope
9
9
{
10
10
kLOCAL ,
11
11
kGLOBAL ,
12
- kFUNCTION_SELF_REF
12
+ kFUNCTION_SELF_REF ,
13
+ kFREE
13
14
};
14
15
15
16
class CurrentFunctionIndex
16
17
{};
17
18
18
19
inline constexpr CurrentFunctionIndex currentFunctionIndex{};
19
20
21
+ using VarInfo = std::pair<size_t , Scope>;
22
+ class SymbolTable
23
+ {
24
+ std::map<std::string, VarInfo> mNameToVarInfo {};
25
+ std::vector<VarInfo> mOrigFreeVars {};
26
+ size_t mNbDefinitions {};
27
+ SymbolTable* mEnclosing {};
28
+ public:
29
+ SymbolTable () = default ;
30
+ SymbolTable (SymbolTable* const enclosing)
31
+ : mEnclosing {enclosing}
32
+ {}
33
+ auto extend ()
34
+ {
35
+ return SymbolTable (this );
36
+ }
37
+ auto defineFreeVar (std::string const & name, VarInfo const & orig)
38
+ {
39
+ auto freeIndex = mOrigFreeVars .size ();
40
+ mOrigFreeVars .push_back (orig);
41
+ auto const freeVar = VarInfo{freeIndex, Scope::kFREE };
42
+ mNameToVarInfo [name] = freeVar;
43
+ return freeVar;
44
+ }
45
+ std::optional<VarInfo> resolve (std::string const & name)
46
+ {
47
+ // found
48
+ auto const & map = mNameToVarInfo ;
49
+ auto const iter = map.find (name);
50
+ if (iter != map.end ())
51
+ {
52
+ return iter->second ;
53
+ }
54
+
55
+ // enclosing
56
+ if (mEnclosing )
57
+ {
58
+ auto const opVarInfo = mEnclosing ->resolve (name);
59
+ if (opVarInfo.has_value ())
60
+ {
61
+ auto const varInfo = opVarInfo.value ();
62
+ if (varInfo.second == Scope::kGLOBAL )
63
+ {
64
+ return varInfo;
65
+ }
66
+ return defineFreeVar (name, varInfo);
67
+ }
68
+ }
69
+
70
+ return {};
71
+ }
72
+
73
+ VarInfo define (std::string const & name, Scope scope)
74
+ {
75
+ auto const index = mNbDefinitions ;
76
+ auto const varInfo = VarInfo{index, scope};
77
+ mNameToVarInfo [name] = varInfo;
78
+ ++mNbDefinitions ;
79
+ return varInfo;
80
+ }
81
+ auto freeVariables () const
82
+ {
83
+ return mOrigFreeVars ;
84
+ }
85
+ };
86
+
20
87
class Compiler
21
88
{
22
- using Index = size_t ;
23
- using SymbolTable = std::map<std::string, Index>;
24
89
SymbolTable mSymbolTable {};
25
90
ByteCode mCode {};
26
91
using FuncInfo = std::tuple<Instructions, SymbolTable, std::string>;
27
- std::optional <FuncInfo> mFunc {};
92
+ std::stack <FuncInfo> mFuncStack {};
28
93
auto & instructions ()
29
94
{
30
- return mFunc ? std::get<0 >(mFunc .value ()) : mCode .instructions ;
95
+ return mFuncStack .empty () ? mCode .instructions : std::get<0 >(mFuncStack .top ());
96
+ }
97
+ auto & symbolTable ()
98
+ {
99
+ return mFuncStack .empty () ? mSymbolTable : std::get<1 >(mFuncStack .top ());
31
100
}
32
- std::pair<Index, Scope> getIndex (std::string const & name) const
101
+ void emitVar (VarInfo const & varInfo);
102
+ void emitIndex (size_t index);
103
+ VarInfo resolve (std::string const & name)
33
104
{
34
- if (mFunc )
105
+ if (mFuncStack . empty () )
35
106
{
36
- auto const & funcInfo = mFunc .value ();
37
- if (name == std::get<2 >(funcInfo))
38
- {
39
- return {0 , Scope::kFUNCTION_SELF_REF };
40
- }
41
- auto const map = std::get<1 >(funcInfo);
42
- auto iter = map.find (name);
43
- if (iter != map.end ())
44
- {
45
- return {iter->second , Scope::kLOCAL };
46
- }
107
+ auto varInfo = mSymbolTable .resolve (name);
108
+ ASSERT_MSG (varInfo, name);
109
+ return varInfo.value ();
110
+ }
111
+
112
+ auto & funcInfo = mFuncStack .top ();
113
+ auto & symTable = std::get<1 >(funcInfo);
114
+ if (auto varInfo = symTable.resolve (name))
115
+ {
116
+ return varInfo.value ();
117
+ }
118
+ // first local args, then self
119
+ if (name == std::get<2 >(funcInfo))
120
+ {
121
+ return {0 , Scope::kFUNCTION_SELF_REF };
47
122
}
48
- auto const idx = mSymbolTable .at (name);
49
- return {idx, Scope::kGLOBAL };
123
+ FAIL_ (" Resolve failed!" );
50
124
}
51
- std::pair<Index, Scope> defineCurrentFunction (std::string const & name)
125
+ VarInfo defineCurrentFunction (std::string const & name)
52
126
{
53
- ASSERT (mFunc );
54
- std::get<2 >(mFunc . value ()) = name;
127
+ ASSERT (! mFuncStack . empty () );
128
+ std::get<2 >(mFuncStack . top ()) = name;
55
129
auto const scope = Scope::kFUNCTION_SELF_REF ;
56
130
return {0 , scope};
57
131
}
58
- std::pair<Index, Scope> define (std::string const & name)
132
+ VarInfo define (std::string const & name)
59
133
{
60
- auto & map = mFunc ? std::get<1 >(mFunc .value ()) : mSymbolTable ;
61
- auto const idx = map.size ();
62
- map[name] = idx;
63
- auto const scope = mFunc ? Scope::kLOCAL : Scope::kGLOBAL ;
64
- return {idx, scope};
134
+ auto const scope = mFuncStack .empty () ? Scope::kGLOBAL : Scope::kLOCAL ;
135
+ return symbolTable ().define (name, scope);
65
136
}
66
137
public:
67
138
Compiler () = default ;
0 commit comments