36 }; |
36 }; |
37 |
37 |
38 // ============================================================================= |
38 // ============================================================================= |
39 // |
39 // |
40 Expression::Expression (BotscriptParser* parser, Lexer* lx, DataType reqtype) : |
40 Expression::Expression (BotscriptParser* parser, Lexer* lx, DataType reqtype) : |
41 mParser (parser), |
41 m_parser (parser), |
42 mLexer (lx), |
42 m_lexer (lx), |
43 mType (reqtype) |
43 m_type (reqtype) |
44 { |
44 { |
45 ExpressionSymbol* sym; |
45 ExpressionSymbol* sym; |
46 |
46 |
47 while ((sym = ParseSymbol()) != null) |
47 while ((sym = parseSymbol()) != null) |
48 mSymbols << sym; |
48 m_symbols << sym; |
49 |
49 |
50 // If we were unable to get any expression symbols, something's wonky with |
50 // If we were unable to get any expression symbols, something's wonky with |
51 // the script. Report an error. mBadTokenText is set to the token that |
51 // the script. Report an error. mBadTokenText is set to the token that |
52 // ParseSymbol ends at when it returns false. |
52 // ParseSymbol ends at when it returns false. |
53 if (mSymbols.IsEmpty()) |
53 if (m_symbols.isEmpty()) |
54 Error ("unknown identifier '%1'", mBadTokenText); |
54 error ("unknown identifier '%1'", m_badTokenText); |
55 |
55 |
56 AdjustOperators(); |
56 adjustOperators(); |
57 Verify(); |
57 verify(); |
58 Evaluate(); |
58 evaluate(); |
59 } |
59 } |
60 |
60 |
61 // ============================================================================= |
61 // ============================================================================= |
62 // |
62 // |
63 Expression::~Expression() |
63 Expression::~Expression() |
64 { |
64 { |
65 for (ExpressionSymbol* sym : mSymbols) |
65 for (ExpressionSymbol* sym : m_symbols) |
66 delete sym; |
66 delete sym; |
67 } |
67 } |
68 |
68 |
69 // ============================================================================= |
69 // ============================================================================= |
70 // |
70 // |
71 // Try to parse an expression symbol (i.e. an OPER_erator or OPER_erand or a colon) |
71 // Try to parse an expression symbol (i.e. an OPER_erator or OPER_erand or a colon) |
72 // from the lexer. |
72 // from the lexer. |
73 // |
73 // |
74 ExpressionSymbol* Expression::ParseSymbol() |
74 ExpressionSymbol* Expression::parseSymbol() |
75 { |
75 { |
76 int pos = mLexer->Position(); |
76 int pos = m_lexer->position(); |
77 ExpressionValue* op = null; |
77 ExpressionValue* op = null; |
78 |
78 |
79 if (mLexer->Next (TK_Colon)) |
79 if (m_lexer->next (TK_Colon)) |
80 return new ExpressionColon; |
80 return new ExpressionColon; |
81 |
81 |
82 // Check for OPER_erator |
82 // Check for OPER_erator |
83 for (const OperatorInfo& op : gOperators) |
83 for (const OperatorInfo& op : g_Operators) |
84 if (mLexer->Next (op.token)) |
84 if (m_lexer->next (op.token)) |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &gOperators[0])); |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0])); |
86 |
86 |
87 // Check sub-expression |
87 // Check sub-expression |
88 if (mLexer->Next (TK_ParenStart)) |
88 if (m_lexer->next (TK_ParenStart)) |
89 { |
89 { |
90 Expression expr (mParser, mLexer, mType); |
90 Expression expr (m_parser, m_lexer, m_type); |
91 mLexer->MustGetNext (TK_ParenEnd); |
91 m_lexer->mustGetNext (TK_ParenEnd); |
92 return expr.Result()->Clone(); |
92 return expr.getResult()->clone(); |
93 } |
93 } |
94 |
94 |
95 op = new ExpressionValue (mType); |
95 op = new ExpressionValue (m_type); |
96 |
96 |
97 // Check function |
97 // Check function |
98 if (CommandInfo* comm = FindCommandByName (mLexer->PeekNextString())) |
98 if (CommandInfo* comm = findCommandByName (m_lexer->peekNextString())) |
99 { |
99 { |
100 mLexer->Skip(); |
100 m_lexer->skip(); |
101 |
101 |
102 if (mType != TYPE_Unknown && comm->returnvalue != mType) |
102 if (m_type != TYPE_Unknown && comm->returnvalue != m_type) |
103 Error ("%1 returns an incompatible data type", comm->name); |
103 error ("%1 returns an incompatible data type", comm->name); |
104 |
104 |
105 op->SetBuffer (mParser->ParseCommand (comm)); |
105 op->setBuffer (m_parser->parseCommand (comm)); |
106 return op; |
106 return op; |
107 } |
107 } |
108 |
108 |
109 // Check for variables |
109 // Check for variables |
110 if (mLexer->Next (TK_DollarSign)) |
110 if (m_lexer->next (TK_DollarSign)) |
111 { |
111 { |
112 mLexer->MustGetNext (TK_Symbol); |
112 m_lexer->mustGetNext (TK_Symbol); |
113 Variable* var = mParser->FindVariable (TokenString()); |
113 Variable* var = m_parser->findVariable (getTokenString()); |
114 |
114 |
115 if (var == null) |
115 if (var == null) |
116 Error ("unknown variable %1", TokenString()); |
116 error ("unknown variable %1", getTokenString()); |
117 |
117 |
118 if (var->type != mType) |
118 if (var->type != m_type) |
119 Error ("expression requires %1, variable $%2 is of type %3", |
119 error ("expression requires %1, variable $%2 is of type %3", |
120 DataTypeName (mType), var->name, DataTypeName (var->type)); |
120 dataTypeName (m_type), var->name, dataTypeName (var->type)); |
121 |
121 |
122 if (var->isarray) |
122 if (var->isarray) |
123 { |
123 { |
124 mLexer->MustGetNext (TK_BracketStart); |
124 m_lexer->mustGetNext (TK_BracketStart); |
125 Expression expr (mParser, mLexer, TYPE_Int); |
125 Expression expr (m_parser, m_lexer, TYPE_Int); |
126 expr.Result()->ConvertToBuffer(); |
126 expr.getResult()->convertToBuffer(); |
127 DataBuffer* buf = expr.Result()->Buffer()->Clone(); |
127 DataBuffer* buf = expr.getResult()->buffer()->clone(); |
128 buf->WriteDWord (DH_PushGlobalArray); |
128 buf->writeDWord (DH_PushGlobalArray); |
129 buf->WriteDWord (var->index); |
129 buf->writeDWord (var->index); |
130 op->SetBuffer (buf); |
130 op->setBuffer (buf); |
131 mLexer->MustGetNext (TK_BracketEnd); |
131 m_lexer->mustGetNext (TK_BracketEnd); |
132 } |
132 } |
133 elif (var->writelevel == WRITE_Constexpr) |
133 elif (var->writelevel == WRITE_Constexpr) |
134 op->SetValue (var->value); |
134 op->setValue (var->value); |
135 else |
135 else |
136 { |
136 { |
137 DataBuffer* buf = new DataBuffer (8); |
137 DataBuffer* buf = new DataBuffer (8); |
138 |
138 |
139 if (var->IsGlobal()) |
139 if (var->IsGlobal()) |
140 buf->WriteDWord (DH_PushGlobalVar); |
140 buf->writeDWord (DH_PushGlobalVar); |
141 else |
141 else |
142 buf->WriteDWord (DH_PushLocalVar); |
142 buf->writeDWord (DH_PushLocalVar); |
143 |
143 |
144 buf->WriteDWord (var->index); |
144 buf->writeDWord (var->index); |
145 op->SetBuffer (buf); |
145 op->setBuffer (buf); |
146 } |
146 } |
147 |
147 |
148 return op; |
148 return op; |
149 } |
149 } |
150 |
150 |
151 // Check for literal |
151 // Check for literal |
152 switch (mType) |
152 switch (m_type) |
153 { |
153 { |
154 case TYPE_Void: |
154 case TYPE_Void: |
155 case TYPE_Unknown: |
155 case TYPE_Unknown: |
156 { |
156 { |
157 Error ("unknown identifier `%1` (expected keyword, function or variable)", TokenString()); |
157 error ("unknown identifier `%1` (expected keyword, function or variable)", getTokenString()); |
158 break; |
158 break; |
159 } |
159 } |
160 |
160 |
161 case TYPE_Bool: |
161 case TYPE_Bool: |
162 { |
162 { |
163 if (mLexer->Next (TK_True) || mLexer->Next (TK_False)) |
163 if (m_lexer->next (TK_True) || m_lexer->next (TK_False)) |
164 { |
164 { |
165 ETokenType tt = mLexer->TokenType(); |
165 ETokenType tt = m_lexer->tokenType(); |
166 op->SetValue (tt == TK_True ? 1 : 0); |
166 op->setValue (tt == TK_True ? 1 : 0); |
167 return op; |
167 return op; |
168 } |
168 } |
169 } |
169 } |
170 |
170 |
171 case TYPE_Int: |
171 case TYPE_Int: |
172 { |
172 { |
173 if (mLexer->Next (TK_Number)) |
173 if (m_lexer->next (TK_Number)) |
174 { |
174 { |
175 op->SetValue (TokenString().ToLong()); |
175 op->setValue (getTokenString().toLong()); |
176 return op; |
176 return op; |
177 } |
177 } |
178 } |
178 } |
179 |
179 |
180 case TYPE_String: |
180 case TYPE_String: |
181 { |
181 { |
182 if (mLexer->Next (TK_String)) |
182 if (m_lexer->next (TK_String)) |
183 { |
183 { |
184 op->SetValue (StringTableIndex (TokenString())); |
184 op->setValue (getStringTableIndex (getTokenString())); |
185 return op; |
185 return op; |
186 } |
186 } |
187 } |
187 } |
188 } |
188 } |
189 |
189 |
190 mBadTokenText = mLexer->Token()->text; |
190 m_badTokenText = m_lexer->token()->text; |
191 mLexer->SetPosition (pos); |
191 m_lexer->setPosition (pos); |
192 delete op; |
192 delete op; |
193 return null; |
193 return null; |
194 } |
194 } |
195 |
195 |
196 // ============================================================================= |
196 // ============================================================================= |
197 // |
197 // |
198 // The symbol parsing process only does token-based checking for OPER_erators. Thus |
198 // The symbol parsing process only does token-based checking for OPER_erators. |
199 // ALL minus OPER_erators are actually unary minuses simply because both have |
199 // Thus ALL minus OPER_erators are actually unary minuses simply because both |
200 //TK_Minus as their token and the unary minus is prior to the binary minus in |
200 // have TK_Minus as their token and the unary minus is prior to the binary minus |
201 // the OPER_erator table. Now that we have all symbols present, we can correct |
201 // in the OPER_erator table. Now that we have all symbols present, we can |
202 // cases like this. |
202 // correct cases like this. |
203 // |
203 // |
204 void Expression::AdjustOperators() |
204 void Expression::adjustOperators() |
205 { |
205 { |
206 for (auto it = mSymbols.begin() + 1; it != mSymbols.end(); ++it) |
206 for (auto it = m_symbols.begin() + 1; it != m_symbols.end(); ++it) |
207 { |
207 { |
208 if ((*it)->Type() != EXPRSYM_Operator) |
208 if ((*it)->type() != EXPRSYM_Operator) |
209 continue; |
209 continue; |
210 |
210 |
211 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
211 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
212 |
212 |
213 // Unary minus with a value as the previous symbol cannot really be |
213 // Unary minus with a value as the previous symbol cannot really be |
214 // unary; replace with binary minus. |
214 // unary; replace with binary minus. |
215 if (op->ID() == OPER_UnaryMinus && (*(it - 1))->Type() == EXPRSYM_Value) |
215 if (op->id() == OPER_UnaryMinus && (*(it - 1))->type() == EXPRSYM_Value) |
216 op->SetID (OPER_Subtraction); |
216 op->setID (OPER_Subtraction); |
217 } |
217 } |
218 } |
218 } |
219 |
219 |
220 // ============================================================================= |
220 // ============================================================================= |
221 // |
221 // |
222 // Verifies a single value. Helper function for Expression::Verify. |
222 // Verifies a single value. Helper function for Expression::verify. |
223 // |
223 // |
224 void Expression::TryVerifyValue (bool* verified, SymbolList::Iterator it) |
224 void Expression::tryVerifyValue (bool* verified, SymbolList::Iterator it) |
225 { |
225 { |
226 // If it's an unary OPER_erator we skip to its value. The actual OPER_erator will |
226 // If it's an unary OPER_erator we skip to its value. The actual OPER_erator will |
227 // be verified separately. |
227 // be verified separately. |
228 if ((*it)->Type() == EXPRSYM_Operator && |
228 if ((*it)->type() == EXPRSYM_Operator && |
229 gOperators[static_cast<ExpressionOperator*> (*it)->ID()].numoperands == 1) |
229 g_Operators[static_cast<ExpressionOperator*> (*it)->id()].numoperands == 1) |
230 { |
230 { |
231 ++it; |
231 ++it; |
232 } |
232 } |
233 |
233 |
234 int i = it - mSymbols.begin(); |
234 int i = it - m_symbols.begin(); |
235 |
235 |
236 // Ensure it's an actual value |
236 // Ensure it's an actual value |
237 if ((*it)->Type() != EXPRSYM_Value) |
237 if ((*it)->type() != EXPRSYM_Value) |
238 Error ("malformed expression (symbol #%1 is not a value)", i); |
238 error ("malformed expression (symbol #%1 is not a value)", i); |
239 |
239 |
240 verified[i] = true; |
240 verified[i] = true; |
241 } |
241 } |
242 |
242 |
243 // ============================================================================= |
243 // ============================================================================= |
244 // |
244 // |
245 // Ensures the expression is valid and well-formed and not OMGWTFBBQ. Throws an |
245 // Ensures the expression is valid and well-formed and not OMGWTFBBQ. Throws an |
246 // error if this is not the case. |
246 // error if this is not the case. |
247 // |
247 // |
248 void Expression::Verify() |
248 void Expression::verify() |
249 { |
249 { |
250 if (mSymbols.Size() == 1) |
250 if (m_symbols.size() == 1) |
251 { |
251 { |
252 if (mSymbols[0]->Type() != EXPRSYM_Value) |
252 if (m_symbols[0]->type() != EXPRSYM_Value) |
253 Error ("bad expression"); |
253 error ("bad expression"); |
254 |
254 |
255 return; |
255 return; |
256 } |
256 } |
257 |
257 |
258 if (mType == TYPE_String) |
258 if (m_type == TYPE_String) |
259 Error ("Cannot perform OPER_erations on strings"); |
259 error ("Cannot perform OPER_erations on strings"); |
260 |
260 |
261 bool* verified = new bool[mSymbols.Size()]; |
261 bool* verified = new bool[m_symbols.size()]; |
262 memset (verified, 0, mSymbols.Size() * sizeof (decltype (*verified))); |
262 memset (verified, 0, m_symbols.size() * sizeof (decltype (*verified))); |
263 const auto last = mSymbols.end() - 1; |
263 const auto last = m_symbols.end() - 1; |
264 const auto first = mSymbols.begin(); |
264 const auto first = m_symbols.begin(); |
265 |
265 |
266 for (auto it = mSymbols.begin(); it != mSymbols.end(); ++it) |
266 for (auto it = m_symbols.begin(); it != m_symbols.end(); ++it) |
267 { |
267 { |
268 int i = (it - first); |
268 int i = (it - first); |
269 |
269 |
270 if ((*it)->Type() != EXPRSYM_Operator) |
270 if ((*it)->type() != EXPRSYM_Operator) |
271 continue; |
271 continue; |
272 |
272 |
273 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
273 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
274 int numoperands = gOperators[op->ID()].numoperands; |
274 int numoperands = g_Operators[op->id()].numoperands; |
275 |
275 |
276 switch (numoperands) |
276 switch (numoperands) |
277 { |
277 { |
278 case 1: |
278 case 1: |
279 { |
279 { |
280 // Ensure that: |
280 // Ensure that: |
281 // - unary OPER_erator is not the last symbol |
281 // - unary OPER_erator is not the last symbol |
282 // - unary OPER_erator is succeeded by a value symbol |
282 // - unary OPER_erator is succeeded by a value symbol |
283 // - neither symbol overlaps with something already verified |
283 // - neither symbol overlaps with something already verified |
284 TryVerifyValue (verified, it + 1); |
284 tryVerifyValue (verified, it + 1); |
285 |
285 |
286 if (it == last || verified[i] == true) |
286 if (it == last || verified[i] == true) |
287 Error ("malformed expression"); |
287 error ("malformed expression"); |
288 |
288 |
289 verified[i] = true; |
289 verified[i] = true; |
290 break; |
290 break; |
291 } |
291 } |
292 |
292 |
321 // - the value behind the OPER_erator (-1) is valid |
321 // - the value behind the OPER_erator (-1) is valid |
322 // - the value after the OPER_erator (+1) is valid |
322 // - the value after the OPER_erator (+1) is valid |
323 // - the value after the colon (+3) is valid |
323 // - the value after the colon (+3) is valid |
324 // - none of the five tokens are verified |
324 // - none of the five tokens are verified |
325 // |
325 // |
326 TryVerifyValue (verified, it - 1); |
326 tryVerifyValue (verified, it - 1); |
327 TryVerifyValue (verified, it + 1); |
327 tryVerifyValue (verified, it + 1); |
328 TryVerifyValue (verified, it + 3); |
328 tryVerifyValue (verified, it + 3); |
329 |
329 |
330 if (it == first || |
330 if (it == first || |
331 it >= mSymbols.end() - 3 || |
331 it >= m_symbols.end() - 3 || |
332 verified[i] == true || |
332 verified[i] == true || |
333 verified[i + 2] == true || |
333 verified[i + 2] == true || |
334 (*(it + 2))->Type() != EXPRSYM_Colon) |
334 (*(it + 2))->type() != EXPRSYM_Colon) |
335 { |
335 { |
336 Error ("malformed expression"); |
336 error ("malformed expression"); |
337 } |
337 } |
338 |
338 |
339 verified[i] = true; |
339 verified[i] = true; |
340 verified[i + 2] = true; |
340 verified[i + 2] = true; |
341 break; |
341 break; |
342 } |
342 } |
343 |
343 |
344 default: |
344 default: |
345 Error ("WTF OPER_erator with %1 OPER_erands", numoperands); |
345 error ("WTF OPER_erator with %1 OPER_erands", numoperands); |
346 } |
346 } |
347 } |
347 } |
348 |
348 |
349 for (int i = 0; i < mSymbols.Size(); ++i) |
349 for (int i = 0; i < m_symbols.size(); ++i) |
350 if (verified[i] == false) |
350 if (verified[i] == false) |
351 Error ("malformed expression: expr symbol #%1 is was left unverified", i); |
351 error ("malformed expression: expr symbol #%1 is was left unverified", i); |
352 |
352 |
353 delete verified; |
353 delete verified; |
354 } |
354 } |
355 |
355 |
356 |
356 |
357 // ============================================================================= |
357 // ============================================================================= |
358 // |
358 // |
359 // Which OPER_erator to evaluate? |
359 // Which operator to evaluate? |
360 // |
360 // |
361 Expression::SymbolList::Iterator Expression::FindPrioritizedOperator() |
361 Expression::SymbolList::Iterator Expression::findPrioritizedOperator() |
362 { |
362 { |
363 SymbolList::Iterator best = mSymbols.end(); |
363 SymbolList::Iterator best = m_symbols.end(); |
364 int bestpriority = __INT_MAX__; |
364 int bestpriority = __INT_MAX__; |
365 |
365 |
366 for (SymbolList::Iterator it = mSymbols.begin(); it != mSymbols.end(); ++it) |
366 for (SymbolList::Iterator it = m_symbols.begin(); it != m_symbols.end(); ++it) |
367 { |
367 { |
368 if ((*it)->Type() != EXPRSYM_Operator) |
368 if ((*it)->type() != EXPRSYM_Operator) |
369 continue; |
369 continue; |
370 |
370 |
371 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
371 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
372 const OperatorInfo* info = &gOperators[op->ID()]; |
372 const OperatorInfo* info = &g_Operators[op->id()]; |
373 |
373 |
374 if (info->priority < bestpriority) |
374 if (info->priority < bestpriority) |
375 { |
375 { |
376 best = it; |
376 best = it; |
377 bestpriority = info->priority; |
377 bestpriority = info->priority; |
383 |
383 |
384 // ============================================================================= |
384 // ============================================================================= |
385 // |
385 // |
386 // Process the given OPER_erator and values into a new value. |
386 // Process the given OPER_erator and values into a new value. |
387 // |
387 // |
388 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op, |
388 ExpressionValue* Expression::evaluateOperator (const ExpressionOperator* op, |
389 const List<ExpressionValue*>& values) |
389 const List<ExpressionValue*>& values) |
390 { |
390 { |
391 const OperatorInfo* info = &gOperators[op->ID()]; |
391 const OperatorInfo* info = &g_Operators[op->id()]; |
392 bool isconstexpr = true; |
392 bool isconstexpr = true; |
393 assert (values.Size() == info->numoperands); |
393 assert (values.size() == info->numoperands); |
394 |
394 |
395 for (ExpressionValue* val : values) |
395 for (ExpressionValue* val : values) |
396 { |
396 { |
397 if (val->IsConstexpr() == false) |
397 if (val->isConstexpr() == false) |
398 { |
398 { |
399 isconstexpr = false; |
399 isconstexpr = false; |
400 break; |
400 break; |
401 } |
401 } |
402 } |
402 } |
403 |
403 |
404 // If not all of the values are constant expressions, none of them shall be. |
404 // If not all of the values are constant expressions, none of them shall be. |
405 if (isconstexpr == false) |
405 if (isconstexpr == false) |
406 for (ExpressionValue* val : values) |
406 for (ExpressionValue* val : values) |
407 val->ConvertToBuffer(); |
407 val->convertToBuffer(); |
408 |
408 |
409 ExpressionValue* newval = new ExpressionValue (mType); |
409 ExpressionValue* newval = new ExpressionValue (m_type); |
410 |
410 |
411 if (isconstexpr == false) |
411 if (isconstexpr == false) |
412 { |
412 { |
413 // This is not a constant expression so we'll have to use databuffers |
413 // This is not a constant expression so we'll have to use databuffers |
414 // to convey the expression to bytecode. Actual value cannot be evaluated |
414 // to convey the expression to bytecode. Actual value cannot be evaluated |
415 // until Zandronum processes it at run-time. |
415 // until Zandronum processes it at run-time. |
416 newval->SetBuffer (new DataBuffer); |
416 newval->setBuffer (new DataBuffer); |
417 |
417 |
418 if (op->ID() == OPER_Ternary) |
418 if (op->id() == OPER_Ternary) |
419 { |
419 { |
420 // There isn't a dataheader for ternary OPER_erator. Instead, we use DH_IfNotGoto |
420 // There isn't a dataheader for ternary OPER_erator. Instead, we use DH_IfNotGoto |
421 // to create an "if-block" inside an expression. |
421 // to create an "if-block" inside an expression. |
422 // Behold, big block of writing madness! :P |
422 // Behold, big block of writing madness! :P |
423 // |
423 // |
424 DataBuffer* buf = newval->Buffer(); |
424 DataBuffer* buf = newval->buffer(); |
425 DataBuffer* b0 = values[0]->Buffer(); |
425 DataBuffer* b0 = values[0]->buffer(); |
426 DataBuffer* b1 = values[1]->Buffer(); |
426 DataBuffer* b1 = values[1]->buffer(); |
427 DataBuffer* b2 = values[2]->Buffer(); |
427 DataBuffer* b2 = values[2]->buffer(); |
428 ByteMark* mark1 = buf->AddMark (""); // start of "else" case |
428 ByteMark* mark1 = buf->addMark (""); // start of "else" case |
429 ByteMark* mark2 = buf->AddMark (""); // end of expression |
429 ByteMark* mark2 = buf->addMark (""); // end of expression |
430 buf->MergeAndDestroy (b0); |
430 buf->mergeAndDestroy (b0); |
431 buf->WriteDWord (DH_IfNotGoto); // if the first OPER_erand (condition) |
431 buf->writeDWord (DH_IfNotGoto); // if the first OPER_erand (condition) |
432 buf->AddReference (mark1); // didn't eval true, jump into mark1 |
432 buf->addReference (mark1); // didn't eval true, jump into mark1 |
433 buf->MergeAndDestroy (b1); // otherwise, perform second OPER_erand (true case) |
433 buf->mergeAndDestroy (b1); // otherwise, perform second OPER_erand (true case) |
434 buf->WriteDWord (DH_Goto); // afterwards, jump to the end, which is |
434 buf->writeDWord (DH_Goto); // afterwards, jump to the end, which is |
435 buf->AddReference (mark2); // marked by mark2. |
435 buf->addReference (mark2); // marked by mark2. |
436 buf->AdjustMark (mark1); // move mark1 at the end of the true case |
436 buf->adjustMark (mark1); // move mark1 at the end of the true case |
437 buf->MergeAndDestroy (b2); // perform third OPER_erand (false case) |
437 buf->mergeAndDestroy (b2); // perform third OPER_erand (false case) |
438 buf->AdjustMark (mark2); // move the ending mark2 here |
438 buf->adjustMark (mark2); // move the ending mark2 here |
439 |
439 |
440 for (int i = 0; i < 3; ++i) |
440 for (int i = 0; i < 3; ++i) |
441 values[i]->SetBuffer (null); |
441 values[i]->setBuffer (null); |
442 } |
442 } |
443 else |
443 else |
444 { |
444 { |
445 // Generic case: write all arguments and apply the OPER_erator's |
445 // Generic case: write all arguments and apply the OPER_erator's |
446 // data header. |
446 // data header. |
447 for (ExpressionValue* val : values) |
447 for (ExpressionValue* val : values) |
448 { |
448 { |
449 newval->Buffer()->MergeAndDestroy (val->Buffer()); |
449 newval->buffer()->mergeAndDestroy (val->buffer()); |
450 |
450 |
451 // Null the pointer out so that the value's destructor will not |
451 // Null the pointer out so that the value's destructor will not |
452 // attempt to double-free it. |
452 // attempt to double-free it. |
453 val->SetBuffer (null); |
453 val->setBuffer (null); |
454 } |
454 } |
455 |
455 |
456 newval->Buffer()->WriteDWord (info->header); |
456 newval->buffer()->writeDWord (info->header); |
457 } |
457 } |
458 } |
458 } |
459 else |
459 else |
460 { |
460 { |
461 // We have a constant expression. We know all the values involved and |
461 // We have a constant expression. We know all the values involved and |
462 // can thus compute the result of this expression on compile-time. |
462 // can thus compute the result of this expression on compile-time. |
463 List<int> nums; |
463 List<int> nums; |
464 int a; |
464 int a; |
465 |
465 |
466 for (ExpressionValue* val : values) |
466 for (ExpressionValue* val : values) |
467 nums << val->Value(); |
467 nums << val->value(); |
468 |
468 |
469 switch (op->ID()) |
469 switch (op->id()) |
470 { |
470 { |
471 case OPER_Addition: a = nums[0] + nums[1]; break; |
471 case OPER_Addition: a = nums[0] + nums[1]; break; |
472 case OPER_Subtraction: a = nums[0] - nums[1]; break; |
472 case OPER_Subtraction: a = nums[0] - nums[1]; break; |
473 case OPER_Multiplication: a = nums[0] * nums[1]; break; |
473 case OPER_Multiplication: a = nums[0] * nums[1]; break; |
474 case OPER_UnaryMinus: a = -nums[0]; break; |
474 case OPER_UnaryMinus: a = -nums[0]; break; |
475 case OPER_NegateLogical: a = !nums[0]; break; |
475 case OPER_NegateLogical: a = !nums[0]; break; |
476 case OPER_LeftShift: a = nums[0] << nums[1]; break; |
476 case OPER_LeftShift: a = nums[0] << nums[1]; break; |
569 |
569 |
570 for (auto it : OPER_erands) |
570 for (auto it : OPER_erands) |
571 values << static_cast<ExpressionValue*> (*it); |
571 values << static_cast<ExpressionValue*> (*it); |
572 |
572 |
573 // Note: @op and all of @values are invalid after this call. |
573 // Note: @op and all of @values are invalid after this call. |
574 ExpressionValue* newvalue = EvaluateOperator (op, values); |
574 ExpressionValue* newvalue = evaluateOperator (op, values); |
575 |
575 |
576 for (int i = upper; i >= lower; --i) |
576 for (int i = upper; i >= lower; --i) |
577 mSymbols.RemoveAt (i); |
577 m_symbols.removeAt (i); |
578 |
578 |
579 mSymbols.Insert (lower, newvalue); |
579 m_symbols.insert (lower, newvalue); |
580 } |
580 } |
581 |
581 |
582 assert (mSymbols.Size() == 1 && mSymbols.First()->Type() == EXPRSYM_Value); |
582 assert (m_symbols.size() == 1 && m_symbols.first()->type() == EXPRSYM_Value); |
583 ExpressionValue* val = static_cast<ExpressionValue*> (mSymbols.First()); |
583 ExpressionValue* val = static_cast<ExpressionValue*> (m_symbols.first()); |
584 return val; |
584 return val; |
585 } |
585 } |
586 |
586 |
587 // ============================================================================= |
587 // ============================================================================= |
588 // |
588 // |
589 ExpressionValue* Expression::Result() |
589 ExpressionValue* Expression::getResult() |
590 { |
590 { |
591 return static_cast<ExpressionValue*> (mSymbols.First()); |
591 return static_cast<ExpressionValue*> (m_symbols.first()); |
592 } |
592 } |
593 |
593 |
594 // ============================================================================= |
594 // ============================================================================= |
595 // |
595 // |
596 String Expression::TokenString() |
596 String Expression::getTokenString() |
597 { |
597 { |
598 return mLexer->Token()->text; |
598 return m_lexer->token()->text; |
599 } |
599 } |
600 |
600 |
601 // ============================================================================= |
601 // ============================================================================= |
602 // |
602 // |
603 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
603 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
604 ExpressionSymbol (EXPRSYM_Operator), |
604 ExpressionSymbol (EXPRSYM_Operator), |
605 mID (id) {} |
605 m_id (id) {} |
606 |
606 |
607 // ============================================================================= |
607 // ============================================================================= |
608 // |
608 // |
609 ExpressionValue::ExpressionValue (DataType valuetype) : |
609 ExpressionValue::ExpressionValue (DataType valuetype) : |
610 ExpressionSymbol (EXPRSYM_Value), |
610 ExpressionSymbol (EXPRSYM_Value), |
611 mBuffer (null), |
611 m_buffer (null), |
612 mValueType (valuetype) {} |
612 m_valueType (valuetype) {} |
613 |
613 |
614 // ============================================================================= |
614 // ============================================================================= |
615 // |
615 // |
616 ExpressionValue::~ExpressionValue() |
616 ExpressionValue::~ExpressionValue() |
617 { |
617 { |
618 delete mBuffer; |
618 delete m_buffer; |
619 } |
619 } |
620 |
620 |
621 // ============================================================================= |
621 // ============================================================================= |
622 // |
622 // |
623 void ExpressionValue::ConvertToBuffer() |
623 void ExpressionValue::convertToBuffer() |
624 { |
624 { |
625 if (IsConstexpr() == false) |
625 if (isConstexpr() == false) |
626 return; |
626 return; |
627 |
627 |
628 SetBuffer (new DataBuffer); |
628 setBuffer (new DataBuffer); |
629 |
629 |
630 switch (mValueType) |
630 switch (m_valueType) |
631 { |
631 { |
632 case TYPE_Bool: |
632 case TYPE_Bool: |
633 case TYPE_Int: |
633 case TYPE_Int: |
634 Buffer()->WriteDWord (DH_PushNumber); |
634 buffer()->writeDWord (DH_PushNumber); |
635 Buffer()->WriteDWord (abs (mValue)); |
635 buffer()->writeDWord (abs (value())); |
636 |
636 |
637 if (mValue < 0) |
637 if (value() < 0) |
638 Buffer()->WriteDWord (DH_UnaryMinus); |
638 buffer()->writeDWord (DH_UnaryMinus); |
639 break; |
639 break; |
640 |
640 |
641 case TYPE_String: |
641 case TYPE_String: |
642 Buffer()->WriteDWord (DH_PushStringIndex); |
642 buffer()->writeDWord (DH_PushStringIndex); |
643 Buffer()->WriteDWord (mValue); |
643 buffer()->writeDWord (value()); |
644 break; |
644 break; |
645 |
645 |
646 case TYPE_Void: |
646 case TYPE_Void: |
647 case TYPE_Unknown: |
647 case TYPE_Unknown: |
648 assert (false); |
648 assert (false); |