-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcodegen.h
More file actions
184 lines (163 loc) · 5.76 KB
/
codegen.h
File metadata and controls
184 lines (163 loc) · 5.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#pragma once
#include "stmt.h"
#include "objects/classcompilationctx.h"
#include "objects/common.h"
#include "objects/customarray.h"
#include "objects/string.h"
class CodeGenerator : public StatementVisitor, public ExpressionVisitor {
private:
int errorsOccurred; // number of errors occurred while compilation
// Because first we compile all declarations, then we compile
// the bodies, making it effectively a two pass compiler.
enum CompilationState {
COMPILE_DECLARATION,
COMPILE_IMPORTS,
COMPILE_BODY
};
enum VariablePosition {
LOCAL,
CLASS,
MODULE,
CORE,
UNDEFINED /*, OBJECT*/
};
typedef struct VarInfo {
int slot;
VariablePosition position;
bool isStatic;
} VarInfo;
// Holds the status of a resolved call
struct CallInfo {
VariablePosition type;
int frameIdx;
bool soft, isStatic;
};
const Class * corectx;
ClassCompilationContext * mtx;
ClassCompilationContext * ctx;
FunctionCompilationContext *ftx;
BytecodeCompilationContext *btx;
CompilationState state;
// Denotes logical scope ordering. Popping a scope with scopeID x
// marks all variables declared in scopeID(s) >= x invalid, so that
// they can't be referenced from a scope with ID < x, i.e. an
// outside scope.
int scopeID;
// to denote whether we are compiling an LHS expression right
// now, so that the compiler does not emit spontaneous bytecodes
// to push the value on the stack
bool onLHS;
// in an LHS, this will contain information about the variable
VarInfo variableInfo;
// to denote whether we are compiling a reference expression
bool onRefer;
// When we are on LHS and the expression is a reference expression,
// this variable will hold the symbol of the ultimate member in that
// expression
int lastMemberReferenced;
// denotes whether the reference expression is part of a 'this.' expression
bool inThis;
// denotes whether the reference expression is part of a 'super.' expression
bool inSuper;
// Denotes whether we are in a class
bool inClass;
// Current visibility when we are in a class
Visibility currentVisibility;
// try markers
int tryBlockStart, tryBlockEnd;
// denotes if we are inside a loop
int inLoop;
// structure to denote a break statement.
struct Break {
size_t ip;
int loopID;
};
// the array of break statements pending patching
CustomArray<Break> pendingBreaks;
// after a loop statement finishes, this method
// patches all break statements defined in scopes
// >= present scope.
void patchBreaks();
// tells expression statement visitor to not pop the result off the stack
bool expressionNoPop;
// Expression generator
void visit(ArrayLiteralExpression *as);
void visit(AssignExpression *as);
void visit(BinaryExpression *bin);
void visit(CallExpression *cal);
void visit(GetExpression *get);
void visit(GetThisOrSuperExpression *get);
void visit(GroupingExpression *group);
void visit(HashmapLiteralExpression *as);
void visit(LiteralExpression *lit);
void visit(MethodReferenceExpression *me);
void visit(PrefixExpression *pe);
void visit(PostfixExpression *pe);
void visit(SetExpression *sete);
void visit(SubscriptExpression *sube);
void visit(VariableExpression *vis);
// Statement generator
void visit(IfStatement *ifs);
void visit(WhileStatement *ifs);
void visit(FnStatement *ifs);
void visit(FnBodyStatement *ifs);
void visit(ClassStatement *ifs);
void visit(TryStatement *ifs);
void visit(CatchStatement *ifs);
void visit(ImportStatement *ifs);
void visit(BlockStatement *ifs);
void visit(ExpressionStatement *ifs);
void visit(VardeclStatement *ifs);
void visit(MemberVariableStatement *ifs);
void visit(VisibilityStatement *ifs);
void visit(ThrowStatement *ifs);
void visit(ReturnStatement *ifs);
void visit(ForStatement *ifs);
void visit(BreakStatement *ifs);
// generates necessary load/store instructions
// based on variableInfo
void loadVariable(VarInfo info, bool isReference = false);
void storeVariable(VarInfo info, bool isReference = false);
void loadCoreModule();
void loadPresentModule();
CallInfo resolveCall(const String2 &name, const String2 &signature);
void emitCall(CallExpression *call);
// validates whether the present lexical scope is
// an appropriate place to refer this/super
void validateThisOrSuper(Token tos);
String * generateSignature(const Token &name, int arity);
String * generateSignature(const String2 &name, int arity);
String * generateSignature(int arity);
VarInfo lookForVariable(Token t, bool declare = false,
bool showError = true,
Visibility vis = VIS_DEFAULT);
VarInfo lookForVariable2(String *name, bool declare = false,
Visibility vis = VIS_DEFAULT, bool force = false);
void compileAll(Array *statements);
void initFtx(FunctionCompilationContext *f, Token t);
void popFrame();
CompilationState getState();
int createTempSlot();
int pushScope();
void popScope(); // discard all variables in present frame with
// scopeID >= present scope
Array *currentlyCompiling;
public:
CodeGenerator();
Class *compile(String *name, Array *statements);
void compile(ClassCompilationContext *compileIn, Array *statements);
void mark();
};
class CodeGeneratorException : public std::runtime_error {
private:
int count;
char message[100];
public:
CodeGeneratorException(int c) : runtime_error("Error"), count(c) {
snprintf(message, 100,
"\n%d error%s occurred while compilation!\nFix them, and try "
"again.",
count, count > 1 ? "s" : "");
}
const char *what() const throw() { return message; }
};