src/Expression.cc

changeset 94
8915ee6a277d
parent 93
11a24b697f43
child 95
4db95b92c29a
equal deleted inserted replaced
93:11a24b697f43 94:8915ee6a277d
34 { tkDoubleAmperstand, 90, 2, dhAndLogical }, 34 { tkDoubleAmperstand, 90, 2, dhAndLogical },
35 { tkDoubleBar, 100, 2, dhOrLogical }, 35 { tkDoubleBar, 100, 2, dhOrLogical },
36 { tkQuestionMark, 110, 3, (EDataHeader) 0 }, 36 { tkQuestionMark, 110, 3, (EDataHeader) 0 },
37 }; 37 };
38 38
39 /*
40 // There isn't a dataheader for ternary operator. Instead, we use dhIfNotGoto
41 // to create an "if-block" inside an expression.
42 // Behold, big block of writing madness! :P
43 ByteMark* mark1 = retbuf->AddMark (""); // start of "else" case
44 ByteMark* mark2 = retbuf->AddMark (""); // end of expression
45 retbuf->WriteDWord (dhIfNotGoto); // if the first operand (condition)
46 retbuf->AddReference (mark1); // didn't eval true, jump into mark1
47 retbuf->MergeAndDestroy (rb); // otherwise, perform second operand (true case)
48 retbuf->WriteDWord (dhGoto); // afterwards, jump to the end, which is
49 retbuf->AddReference (mark2); // marked by mark2.
50 retbuf->AdjustMark (mark1); // move mark1 at the end of the true case
51 retbuf->MergeAndDestroy (tb); // perform third operand (false case)
52 retbuf->AdjustMark (mark2); // move the ending mark2 here
53 */
54
55 // ============================================================================= 39 // =============================================================================
56 // 40 //
57 Expression::Expression (BotscriptParser* parser, Lexer* lx, EType reqtype) : 41 Expression::Expression (BotscriptParser* parser, Lexer* lx, EType reqtype) :
58 mParser (parser), 42 mParser (parser),
59 mLexer (lx), 43 mLexer (lx),
60 mType (reqtype), 44 mType (reqtype)
61 mResult (null)
62 { 45 {
63 ExpressionSymbol* sym; 46 ExpressionSymbol* sym;
64 47
65 while ((sym = ParseSymbol()) != null) 48 while ((sym = ParseSymbol()) != null)
66 mSymbols << sym; 49 mSymbols << sym;
67 50
68 if (mSymbols.IsEmpty()) 51 if (mSymbols.IsEmpty())
69 Error ("Expected expression"); 52 Error ("Expected expression");
70 53
71 AdjustOperators(); 54 AdjustOperators();
72
73 for (ExpressionSymbol* sym : mSymbols)
74 {
75 switch (sym->GetType())
76 {
77 case eOperatorSymbol:
78 {
79 Print ("\t- Operator: %1\n", static_cast<ExpressionOperator*> (sym)->GetID());
80 break;
81 }
82
83 case eValueSymbol:
84 {
85 ExpressionValue* val = static_cast<ExpressionValue*> (sym);
86
87 if (val->IsConstexpr())
88 Print ("\t- Constant expression value: %1\n", val->GetValue());
89 else
90 {
91 Print ("\t- Databuffer value:\n");
92 val->GetBuffer()->Dump();
93 }
94 break;
95 }
96
97 case eColonSymbol:
98 {
99 Print ("\t- Colon");
100 break;
101 }
102 }
103 }
104
105 Verify(); 55 Verify();
106 exit (0); 56 Evaluate();
107
108 /*
109 mResult = Evaluate();
110 */
111 } 57 }
112 58
113 // ============================================================================= 59 // =============================================================================
114 // 60 //
115 Expression::~Expression() 61 Expression::~Expression()
116 { 62 {
117 for (ExpressionSymbol* sym : mSymbols) 63 for (ExpressionSymbol* sym : mSymbols)
118 delete sym; 64 delete sym;
119
120 delete mResult;
121 } 65 }
122 66
123 // ============================================================================= 67 // =============================================================================
124 // 68 //
125 // Try to parse an expression symbol (i.e. an operator or operand or a colon) 69 // Try to parse an expression symbol (i.e. an operator or operand or a colon)
149 // Check sub-expression 93 // Check sub-expression
150 if (mLexer->GetTokenType() == tkParenStart) 94 if (mLexer->GetTokenType() == tkParenStart)
151 { 95 {
152 Expression expr (mParser, mLexer, mType); 96 Expression expr (mParser, mLexer, mType);
153 mLexer->MustGetNext (tkParenEnd); 97 mLexer->MustGetNext (tkParenEnd);
154 return expr.GetResult(); 98 return expr.GetResult()->Clone();
155 } 99 }
156 100
157 op = new ExpressionValue (mType); 101 op = new ExpressionValue (mType);
158 102
159 // Check function 103 // Check function
310 if (mSymbols.Size() == 1) 254 if (mSymbols.Size() == 1)
311 { 255 {
312 if (mSymbols[0]->GetType() != eValueSymbol) 256 if (mSymbols[0]->GetType() != eValueSymbol)
313 Error ("bad expression"); 257 Error ("bad expression");
314 258
315 Print ("Expression speedy-verified (1 expr symbol)"); 259 Print ("Expression speedy-verified (1 expr symbol)\n");
316 return; 260 return;
317 } 261 }
262
263 if (mType == EStringType)
264 Error ("Cannot perform operations on strings");
318 265
319 bool* verified = new bool[mSymbols.Size()]; 266 bool* verified = new bool[mSymbols.Size()];
320 memset (verified, 0, mSymbols.Size() * sizeof (decltype (*verified))); 267 memset (verified, 0, mSymbols.Size() * sizeof (decltype (*verified)));
321 const auto last = mSymbols.end() - 1; 268 const auto last = mSymbols.end() - 1;
322 const auto first = mSymbols.begin(); 269 const auto first = mSymbols.begin();
407 for (int i = 0; i < mSymbols.Size(); ++i) 354 for (int i = 0; i < mSymbols.Size(); ++i)
408 if (verified[i] == false) 355 if (verified[i] == false)
409 Error ("malformed expression: expr symbol #%1 is was left unverified", i); 356 Error ("malformed expression: expr symbol #%1 is was left unverified", i);
410 357
411 Print ("Expression verified.\n"); 358 Print ("Expression verified.\n");
359 delete verified;
360 }
361
362
363 // =============================================================================
364 //
365 // Which operator to evaluate?
366 //
367 Expression::SymbolList::Iterator Expression::FindPrioritizedOperator()
368 {
369 SymbolList::Iterator best = mSymbols.end();
370 int bestpriority = INT_MAX;
371
372 for (SymbolList::Iterator it = mSymbols.begin(); it != mSymbols.end(); ++it)
373 {
374 if ((*it)->GetType() != eOperatorSymbol)
375 continue;
376
377 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it);
378 const OperatorInfo* info = &gOperators[op->GetID()];
379
380 if (info->priority < bestpriority)
381 {
382 best = it;
383 bestpriority = info->priority;
384 }
385 }
386
387 return best;
388 }
389
390 // =============================================================================
391 //
392 // Process the given operator and values into a new value.
393 //
394 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op,
395 const List<ExpressionValue*>& values)
396 {
397 const OperatorInfo* info = &gOperators[op->GetID()];
398 bool isconstexpr = true;
399
400 for (ExpressionValue* val : values)
401 {
402 if (val->IsConstexpr() == false)
403 {
404 isconstexpr = false;
405 break;
406 }
407 }
408
409 // If not all of the values are constant expressions, none of them shall be.
410 if (isconstexpr == false)
411 for (ExpressionValue* val : values)
412 val->ConvertToBuffer();
413
414 ExpressionValue* newval = new ExpressionValue (mType);
415
416 if (isconstexpr == false)
417 newval->SetBuffer (new DataBuffer);
418
419 if (isconstexpr == false)
420 {
421 if (op->GetID() == opTernary)
422 {
423 // There isn't a dataheader for ternary operator. Instead, we use dhIfNotGoto
424 // to create an "if-block" inside an expression.
425 // Behold, big block of writing madness! :P
426 //
427 DataBuffer* buf = newval->GetBuffer();
428 DataBuffer* b0 = values[0]->GetBuffer();
429 DataBuffer* b1 = values[1]->GetBuffer();
430 DataBuffer* b2 = values[2]->GetBuffer();
431 ByteMark* mark1 = buf->AddMark (""); // start of "else" case
432 ByteMark* mark2 = buf->AddMark (""); // end of expression
433 buf->MergeAndDestroy (b0);
434 buf->WriteDWord (dhIfNotGoto); // if the first operand (condition)
435 buf->AddReference (mark1); // didn't eval true, jump into mark1
436 buf->MergeAndDestroy (b1); // otherwise, perform second operand (true case)
437 buf->WriteDWord (dhGoto); // afterwards, jump to the end, which is
438 buf->AddReference (mark2); // marked by mark2.
439 buf->AdjustMark (mark1); // move mark1 at the end of the true case
440 buf->MergeAndDestroy (b2); // perform third operand (false case)
441 buf->AdjustMark (mark2); // move the ending mark2 here
442 }
443 else
444 {
445 // Generic case: write all arguments and apply the operator's
446 // data header.
447 for (ExpressionValue* val : values)
448 {
449 newval->GetBuffer()->MergeAndDestroy (val->GetBuffer());
450
451 // Null the pointer out so that the value's destructor will not
452 // attempt to double-free it.
453 val->SetBuffer (null);
454 }
455
456 newval->GetBuffer()->WriteDWord (info->header);
457 }
458 }
459 else
460 {
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.
463 List<int> nums;
464 int a;
465
466 for (ExpressionValue* val : values)
467 nums << val->GetValue();
468
469 switch (op->GetID())
470 {
471 case opAddition: a = nums[0] + nums[1]; break;
472 case opSubtraction: a = nums[0] - nums[1]; break;
473 case opMultiplication: a = nums[0] * nums[1]; break;
474 case opUnaryMinus: a = -nums[0]; break;
475 case opNegateLogical: a = !nums[0]; break;
476 case opLeftShift: a = nums[0] << nums[1]; break;
477 case opRightShift: a = nums[0] >> nums[1]; break;
478 case opCompareLesser: a = (nums[0] < nums[1]) ? 1 : 0; break;
479 case opCompareGreater: a = (nums[0] > nums[1]) ? 1 : 0; break;
480 case opCompareAtLeast: a = (nums[0] <= nums[1]) ? 1 : 0; break;
481 case opCompareAtMost: a = (nums[0] >= nums[1]) ? 1 : 0; break;
482 case opCompareEquals: a = (nums[0] == nums[1]) ? 1 : 0; break;
483 case opCompareNotEquals: a = (nums[0] != nums[1]) ? 1 : 0; break;
484 case opBitwiseAnd: a = nums[0] & nums[1]; break;
485 case opBitwiseOr: a = nums[0] | nums[1]; break;
486 case opBitwiseXOr: a = nums[0] ^ nums[1]; break;
487 case opLogicalAnd: a = (nums[0] && nums[1]) ? 1 : 0; break;
488 case opLogicalOr: a = (nums[0] || nums[1]) ? 1 : 0; break;
489 case opTernary: a = (nums[0] != 0) ? nums[1] : nums[2]; break;
490
491 case opDivision:
492 if (nums[1] == 0)
493 Error ("division by zero in constant expression");
494
495 a = nums[0] / nums[1];
496 break;
497
498 case opModulus:
499 if (nums[1] == 0)
500 Error ("modulus by zero in constant expression");
501
502 a = nums[0] % nums[1];
503 break;
504 }
505
506 newval->SetValue (a);
507 }
508
509 // The new value has been generated. We don't need the old stuff anymore.
510 for (ExpressionValue* val : values)
511 delete val;
512
513 delete op;
514 return newval;
412 } 515 }
413 516
414 // ============================================================================= 517 // =============================================================================
415 // 518 //
416 ExpressionValue* Expression::Evaluate() 519 ExpressionValue* Expression::Evaluate()
417 { 520 {
418 521 SymbolList::Iterator it;
522
523 while ((it = FindPrioritizedOperator()) != mSymbols.end())
524 {
525 int i = it - mSymbols.begin();
526 List<SymbolList::Iterator> operands;
527 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it);
528 const OperatorInfo* info = &gOperators[op->GetID()];
529 int lower, upper; // Boundaries of area to replace
530
531 switch (info->numoperands)
532 {
533 case 1:
534 {
535 lower = i;
536 upper = i + 1;
537 operands << it + 1;
538 break;
539 }
540
541 case 2:
542 {
543 lower = i - 1;
544 upper = i + 1;
545 operands << it - 1
546 << it + 1;
547 break;
548 }
549
550 case 3:
551 {
552 lower = i - 1;
553 upper = i + 3;
554 operands << it - 1
555 << it + 1
556 << it + 3;
557 break;
558 }
559
560 default:
561 assert (false);
562 }
563
564 List<ExpressionValue*> values;
565
566 for (auto it : operands)
567 values << static_cast<ExpressionValue*> (*it);
568
569 // Note: @op and all of @values are invalid after this call.
570 ExpressionValue* newvalue = EvaluateOperator (op, values);
571
572 for (int i = upper; i >= lower; --i)
573 mSymbols.RemoveAt (i);
574
575 mSymbols.Insert (lower, newvalue);
576 }
577
578 assert (mSymbols.Size() == 1 && mSymbols.First()->GetType() == eValueSymbol);
579 ExpressionValue* val = static_cast<ExpressionValue*> (mSymbols.First());
580 return val;
419 } 581 }
420 582
421 // ============================================================================= 583 // =============================================================================
422 // 584 //
423 ExpressionValue* Expression::GetResult() 585 ExpressionValue* Expression::GetResult()
424 { 586 {
425 return mResult; 587 return static_cast<ExpressionValue*> (mSymbols.First());
426 } 588 }
427 589
428 // ============================================================================= 590 // =============================================================================
429 // 591 //
430 String Expression::GetTokenString() 592 String Expression::GetTokenString()

mercurial