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) |
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() |