this repo has no description
1#include "ResourceDefinitions.h"
2#include <ostream>
3#include <cassert>
4
5#include "ResourceCompiler.h"
6#include "Diagnostic.h"
7
8
9std::ostream &operator<<(std::ostream &out, TypeSpec ts)
10{
11 out << ts.getType();
12 if(ts.hasID())
13 out << " (" << ts.getID() << ")";
14 return out;
15}
16
17
18FieldList::~FieldList()
19{
20
21}
22
23void FieldList::addField(FieldPtr field, yy::location loc)
24{
25 field->location = loc;
26 fields.push_back(field);
27}
28
29void FieldList::addLabel(std::string name, yy::location loc)
30{
31 addField(std::make_shared<LabelField>(name), loc);
32}
33
34void FieldList::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
35{
36 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr);
37 assert(compound);
38
39 int i = 0;
40 for(FieldPtr f : fields)
41 {
42 if(f->needsValue())
43 {
44 if(i >= compound->size())
45 compiler->problem(Diagnostic(Diagnostic::error,"not enough values specified", compound->location));
46 else
47 f->compile(compound->getItem(i++), compiler, prePass);
48 }
49 else
50 f->compile(nullptr, compiler, prePass);
51 }
52 if(i < compound->size())
53 {
54 compiler->problem(Diagnostic(Diagnostic::error,"extra value specified",
55 compound->getItem(i)->location));
56 }
57}
58
59
60
61
62void SimpleField::addNamedValue(std::string n)
63{
64 if(lastNamedValue)
65 addNamedValue(n, std::make_shared<BinaryExpr>(
66 BinaryOp::PLUS, lastNamedValue, std::make_shared<IntExpr>(1, yy::location()), yy::location()));
67 else
68 addNamedValue(n, std::make_shared<IntExpr>(0, yy::location()));
69}
70
71void SimpleField::addNamedValue(std::string n, ExprPtr val)
72{
73 namedValues[n] = val;
74 lastNamedValue = val;
75}
76
77ExprPtr SimpleField::lookupNamedValue(std::string n)
78{
79 auto p = namedValues.find(n);
80 if(p != namedValues.end())
81 return p->second;
82 else
83 return nullptr;
84}
85
86bool SimpleField::needsValue()
87{
88 return !value;
89}
90
91void SimpleField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
92{
93 switch(type)
94 {
95 case Type::bitstring:
96 case Type::boolean:
97 case Type::byte:
98 case Type::integer:
99 case Type::longint:
100 compileInt(expr, compiler, prePass);
101 break;
102 case Type::string:
103 case Type::wstring:
104 case Type::pstring:
105 case Type::char_:
106 compileString(expr, compiler, prePass);
107 break;
108
109 case Type::rect:
110 case Type::point:
111 compileCompound(expr, compiler, prePass);
112 break;
113
114 }
115}
116
117void SimpleField::compileString(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
118{
119 std::string str;
120 {
121 ResourceCompiler::FieldScope scope(compiler, this);
122 str = (value ? value : expr)->evaluateString(compiler);
123 }
124
125 if(arrayCount || type == Type::char_)
126 {
127 unsigned requestedSize = type == Type::char_ ? 1 : arrayCount->evaluateInt(compiler);
128 if(requestedSize < str.size())
129 str.erase(str.begin() + requestedSize, str.end());
130 else if(requestedSize > str.size())
131 str.insert(str.end(),requestedSize - str.size(), '\0');
132 }
133
134 int count = str.size();
135
136 if(type == Type::pstring)
137 {
138 if(count > 255)
139 {
140 str.erase(str.begin() + 255, str.end());
141 count = 255;
142 }
143 compiler->write(8, count);
144 }
145 else if(type == Type::wstring)
146 {
147 if(count > 65535)
148 {
149 str.erase(str.begin() + 65535, str.end());
150 count = 65535;
151 }
152 compiler->write(16, count);
153 }
154
155 for(char c : str)
156 compiler->write(8, c);
157}
158
159void SimpleField::compileInt(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
160{
161 int bitSize = 0;
162
163 switch(type)
164 {
165 case Type::bitstring:
166 bitSize = arrayCount->evaluateInt(compiler);
167 break;
168 case Type::boolean:
169 bitSize = 1;
170 break;
171 case Type::byte:
172 bitSize = 8;
173 break;
174 case Type::integer:
175 bitSize = 16;
176 break;
177 case Type::longint:
178 bitSize = 32;
179 break;
180 default:
181 assert(false);
182 }
183
184 int actualValue = 0;
185 ResourceCompiler::FieldScope scope(compiler, this);
186 actualValue = (value ? value : expr)->evaluateInt(compiler);
187
188 compiler->write(bitSize, actualValue);
189}
190
191void SimpleField::compileCompound(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
192{
193 ExprPtr val = value ? value : expr;
194 if(IdentifierExprPtr id = std::dynamic_pointer_cast<IdentifierExpr>(val))
195 {
196 ResourceCompiler::FieldScope scope(compiler, this);
197 val = id->lookup(compiler);
198 }
199
200 int count = 0;
201 switch(type)
202 {
203 case Type::rect:
204 count = 4;
205 break;
206 case Type::point:
207 count = 2;
208 break;
209 default:
210 assert(false);
211 }
212
213 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(val);
214 if(!compound || compound->size() != count)
215 {
216 expr->error(compiler, std::string("expected ") + (type == Type::rect ? "rect {t,l,b,r}." : "point {v,h}."));
217 return;
218 }
219 assert(compound);
220 assert(compound->size() == count);
221
222 for(int i = 0; i < count; i++)
223 {
224 int x = compound->getItem(i)->evaluateInt(compiler);
225 compiler->write(16, x);
226 }
227}
228
229
230ArrayField::ArrayField(std::string name, ExprPtr count)
231 : name(name), arrayCount(count)
232{
233}
234
235void ArrayField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
236{
237 CompoundExprPtr compound = std::dynamic_pointer_cast<CompoundExpr>(expr);
238 assert(compound);
239
240
241 int i = 0;
242 int n = compound->size();
243
244 int iterations = 0;
245 while(i < n)
246 {
247 ++iterations;
248 ResourceCompiler::ArrayScope scope(compiler, name, iterations);
249 for(FieldPtr f : fields)
250 {
251 if(f->needsValue())
252 {
253 assert(i < n);
254 f->compile(compound->getItem(i++), compiler, prePass);
255 }
256 else
257 f->compile(nullptr, compiler, prePass);
258 }
259 }
260
261 if(!prePass && arrayCount)
262 {
263 int expected = arrayCount->evaluateInt(compiler);
264 assert(expected == iterations);
265 }
266}
267
268
269LabelField::LabelField(std::string name)
270 : name(name)
271{
272}
273
274bool LabelField::needsValue()
275{
276 return false;
277}
278
279void LabelField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
280{
281 compiler->defineLabel(name);
282}
283
284
285void SwitchField::addCase(const std::string name, FieldListPtr alternative)
286{
287 cases[name] = alternative;
288}
289
290void SwitchField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
291{
292 CaseExprPtr caseExpr = std::dynamic_pointer_cast<CaseExpr>(expr);
293 assert(caseExpr);
294
295 FieldListPtr caseDefinition = cases[caseExpr->tag];
296 assert(caseDefinition);
297
298 caseDefinition->compile(caseExpr->expr, compiler, prePass);
299}
300
301
302FillAlignField::FillAlignField(FillAlignField::Type type, bool isAlign, ExprPtr count)
303 : type(type), count(count), isAlign(isAlign)
304{
305
306}
307
308bool FillAlignField::needsValue()
309{
310 return false;
311}
312
313void FillAlignField::compile(ExprPtr expr, ResourceCompiler *compiler, bool prePass)
314{
315 int bitSize;
316 switch(type)
317 {
318 case Type::bit: bitSize = 1; break;
319 case Type::nibble: bitSize = 4; break;
320 case Type::byte: bitSize = 8; break;
321 case Type::word: bitSize = 16; break;
322 case Type::long_: bitSize = 32; break;
323 }
324
325 int actualCount = 1;
326 if(count)
327 actualCount = count->evaluateInt(compiler);
328
329 for(int i = 0; i < actualCount; i++)
330 {
331 int n;
332 if(isAlign)
333 {
334 int mask = bitSize - 1;
335 int pos = compiler->tell();
336 n = ((pos + mask) & ~mask) - pos;
337 }
338 else
339 n = bitSize;
340 compiler->write(n, 0);
341 }
342}