-
-
Notifications
You must be signed in to change notification settings - Fork 78
/
LibrarySymbols.cpp
312 lines (286 loc) · 9.75 KB
/
LibrarySymbols.cpp
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#include "symbols/SymbolDefs.h"
#include <fmt/format.h>
#include <sstream>
AccessorTable::AccessorTable(std::string const& name, byte tag, int32_t rettype,
int32_t var, int32_t flags,
vector<int32_t>const& params, vector<int32_t> const& optparams,
byte extra_vargs, string const& info)
: name(name), tag(tag), rettype(rettype), var(var),
funcFlags(flags), params(params),
optparams(optparams), extra_vargs(extra_vargs), info(info)
{}
LibrarySymbols LibrarySymbols::nilsymbols = LibrarySymbols();
LibrarySymbols* LibrarySymbols::getTypeInstance(DataTypeId typeId)
{
switch (typeId)
{
case ZTID_FFC: return &FFCSymbols::getInst();
case ZTID_PLAYER: return &HeroSymbols::getInst();
case ZTID_SCREEN: return &ScreenSymbols::getInst();
case ZTID_REGION: return &RegionSymbols::getInst();
case ZTID_GAME: return &GameSymbols::getInst();
case ZTID_ITEM: return &ItemSymbols::getInst();
case ZTID_ITEMCLASS: return &ItemclassSymbols::getInst();
case ZTID_NPC: return &NPCSymbols::getInst();
case ZTID_LWPN: return &HeroWeaponSymbols::getInst();
case ZTID_EWPN: return &EnemyWeaponSymbols::getInst();
case ZTID_NPCDATA: return &NPCDataSymbols::getInst();
case ZTID_DEBUG: return &DebugSymbols::getInst();
case ZTID_AUDIO: return &AudioSymbols::getInst();
case ZTID_COMBOS: return &CombosPtrSymbols::getInst();
case ZTID_SPRITEDATA: return &SpriteDataSymbols::getInst();
case ZTID_GRAPHICS: return &GraphicsSymbols::getInst();
case ZTID_BITMAP: return &BitmapSymbols::getInst();
case ZTID_TEXT: return &TextPtrSymbols::getInst();
case ZTID_INPUT: return &InputSymbols::getInst();
case ZTID_MAPDATA: return &MapDataSymbols::getInst();
case ZTID_DMAPDATA: return &DMapDataSymbols::getInst();
case ZTID_ZMESSAGE: return &MessageDataSymbols::getInst();
case ZTID_SHOPDATA: return &ShopDataSymbols::getInst();
case ZTID_DROPSET: return &DropsetSymbols::getInst();
case ZTID_FILESYSTEM: return &FileSystemSymbols::getInst();
case ZTID_FILE: return &FileSymbols::getInst();
case ZTID_DIRECTORY: return &DirectorySymbols::getInst();
case ZTID_STACK: return &StackSymbols::getInst();
case ZTID_ZINFO: return &ZInfoSymbols::getInst();
case ZTID_RNG: return &RNGSymbols::getInst();
case ZTID_PALDATA: return &PalDataSymbols::getInst();
case ZTID_BOTTLETYPE: return &BottleTypeSymbols::getInst();
case ZTID_BOTTLESHOP: return &BottleShopSymbols::getInst();
case ZTID_GENERICDATA: return &GenericDataSymbols::getInst();
case ZTID_PORTAL: return &PortalSymbols::getInst();
case ZTID_SAVPORTAL: return &SavedPortalSymbols::getInst();
case ZTID_SUBSCREENDATA: return &SubscreenDataSymbols::getInst();
case ZTID_SUBSCREENPAGE: return &SubscreenPageSymbols::getInst();
case ZTID_SUBSCREENWIDGET: return &SubscreenWidgetSymbols::getInst();
default: return &nilsymbols;
}
}
void getConstant(int32_t refVar, Function* function, int32_t val)
{
if(refVar != NUL)
{
throw compile_exception(fmt::format("Internal Constant {} has non-NUL refVar!", function->name));
}
function->setFlag(FUNCFLAG_INLINE);
function->internal_flags |= IFUNCFLAG_SKIPPOINTER;
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
addOpcode2(code, new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(val)));
LABELBACK(label);
function->giveCode(code);
}
void getVariable(int32_t refVar, Function* function, int32_t var)
{
function->setFlag(FUNCFLAG_INLINE);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
//pop object pointer
if(refVar == NUL)
{
function->internal_flags |= IFUNCFLAG_SKIPPOINTER;
addOpcode2 (code, new OSetRegister(new VarArgument(EXP1), new VarArgument(var)));
LABELBACK(label);
}
else
{
//Pop object pointer
addOpcode2 (code, new OPopRegister(new VarArgument(refVar)));
LABELBACK(label);
addOpcode2 (code, new OSetRegister(new VarArgument(EXP1), new VarArgument(var)));
}
RETURN();
function->giveCode(code);
}
void getIndexedVariable(int32_t refVar, Function* function, int32_t var)
{
function->setFlag(FUNCFLAG_INLINE);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
//pop index
addOpcode2 (code, new OPopRegister(new VarArgument(INDEX)));
LABELBACK(label);
//pop object pointer
POPREF();
addOpcode2 (code, new OSetRegister(new VarArgument(EXP1), new VarArgument(var)));
RETURN();
function->giveCode(code);
}
void setVariable(int32_t refVar, Function* function, int32_t var)
{
function->setFlag(FUNCFLAG_INLINE);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
//pop off the value to set to
addOpcode2 (code, new OPopRegister(new VarArgument(EXP1)));
LABELBACK(label);
//pop object pointer
POPREF();
addOpcode2 (code, new OSetRegister(new VarArgument(var), new VarArgument(EXP1)));
RETURN();
function->giveCode(code);
}
void setBoolVariable(int32_t refVar, Function* function, int32_t var)
{
function->setFlag(FUNCFLAG_INLINE);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
//pop off the value to set to
addOpcode2 (code, new OPopRegister(new VarArgument(EXP1)));
LABELBACK(label);
//renormalize true to 1
addOpcode2 (code, new OCastBoolI(new VarArgument(EXP1)));
POPREF();
addOpcode2 (code, new OSetRegister(new VarArgument(var), new VarArgument(EXP1)));
RETURN();
function->giveCode(code);
}
void setIndexedVariable(int32_t refVar, Function* function, int32_t var)
{
function->setFlag(FUNCFLAG_INLINE);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
//pop off index
addOpcode2 (code, new OPopRegister(new VarArgument(INDEX)));
LABELBACK(label);
//pop off the value to set to
addOpcode2 (code, new OPopRegister(new VarArgument(EXP1)));
//pop object pointer
POPREF();
addOpcode2 (code, new OSetRegister(new VarArgument(var), new VarArgument(EXP1)));
RETURN();
function->giveCode(code);
}
void handleNil(int32_t refVar, Function* function)
{
function->setFlag(FUNCFLAG_INLINE);
if(refVar == NUL)
function->setFlag(IFUNCFLAG_SKIPPOINTER);
int32_t label = function->getLabel();
vector<shared_ptr<Opcode>> code;
addOpcode2(code, new ONoOp());
LABELBACK(label);
function->giveCode(code);
}
void LibrarySymbols::addSymbolsToScope(Scope& scope)
{
if(!table) return;
TypeStore& typeStore = scope.getTypeStore();
vector<string const*> blankParams;
std::ostringstream errorstream;
for (int32_t i = 0; table[i].name != ""; i++)
{
try
{
AccessorTable& entry = table[i];
std::string const& name = entry.name;
std::string varName = name;
// Strip out the array at the end.
bool isArray = name.substr(name.size() - 2) == "[]";
if (isArray)
varName = name.substr(0, name.size() - 2);
DataType const* returnType = typeStore.getType(entry.rettype);
vector<DataType const*> paramTypes;
for (auto& ptype : entry.params)
paramTypes.push_back(typeStore.getType(ptype));
// Create function object.
auto setorget = FUNCTION;
Function* function = nullptr;
if (name.substr(0, 5) == "const")
{
setorget = CONSTANT;
varName = varName.substr(5); // Strip out "const"
function = scope.addGetter(returnType, varName, paramTypes, blankParams, entry.funcFlags);
}
else if (entry.var > -1 && name.substr(0, 3) == "set")
{
setorget = SETTER;
varName = varName.substr(3); // Strip out "set".
function = scope.addSetter(returnType, varName, paramTypes, blankParams, entry.funcFlags);
}
else if (entry.var > -1 && name.substr(0, 3) == "get")
{
setorget = GETTER;
varName = varName.substr(3); // Strip out "get".
function = scope.addGetter(returnType, varName, paramTypes, blankParams, entry.funcFlags);
}
else
{
if(name.substr(0,4) == "_set")
{
setorget = SETTER;
varName = varName.substr(4); // Strip out "_set".
}
else if(name.substr(0,4) == "_get")
{
setorget = GETTER;
varName = varName.substr(4); // Strip out "_get".
}
function = scope.addFunction(returnType, varName, paramTypes, blankParams, entry.funcFlags);
}
if(!function)
throw compile_exception(fmt::format("Failed to create internal function '{}', {}\n",name,entry.tag));
functions[make_pair(name,entry.tag)] = function;
if(hasPrefixType)
function->hasPrefixType = true; //Print the first type differently in error messages!
function->opt_vals = entry.optparams;
function->info = entry.info;
if(function->getFlag(FUNCFLAG_VARARGS))
{
function->extra_vargs = entry.extra_vargs;
function->setFlag(FUNCFLAG_INLINE);
}
// Generate function code for getters/setters
int32_t label = function->getLabel();
if(function->isNil())
{
handleNil(refVar, function);
}
else switch(setorget)
{
case GETTER:
if (isArray)
getIndexedVariable(refVar, function, entry.var);
else
getVariable(refVar, function, entry.var);
break;
case SETTER:
if (isArray)
setIndexedVariable(refVar, function, entry.var);
else if (entry.params.size() > 1 && entry.params[1] == ZTID_BOOL)
setBoolVariable(refVar, function, entry.var);
else
setVariable(refVar, function, entry.var);
break;
case CONSTANT:
getConstant(refVar, function, entry.var);
break;
}
}
catch(std::exception &e)
{
errorstream << e.what() << '\n';
}
}
try
{
generateCode();
}
catch (std::exception& e)
{
errorstream << e.what() << '\n';
}
functions.clear();
std::string errors = errorstream.str();
if(!errors.empty())
throw compile_exception(errors);
}
Function* LibrarySymbols::getFunction(std::string const& name, byte tag) const
{
std::pair<std::string, int32_t> p = make_pair(name, tag);
Function* ret = find<Function*>(functions, p).value_or(nullptr);
if(!ret)
throw compile_exception(fmt::format("Unique internal function {} not found with tag {}!", name, tag));
return ret;
}
LibrarySymbols::~LibrarySymbols(){}