| 2 #include "dataBuffer.h" |
2 #include "dataBuffer.h" |
| 3 #include "lexer.h" |
3 #include "lexer.h" |
| 4 |
4 |
| 5 struct OperatorInfo |
5 struct OperatorInfo |
| 6 { |
6 { |
| 7 ETokenType token; |
7 Token token; |
| 8 int priority; |
8 int priority; |
| 9 int numoperands; |
9 int numoperands; |
| 10 DataHeader header; |
10 DataHeader header; |
| 11 }; |
11 }; |
| 12 |
12 |
| 13 static const OperatorInfo g_Operators[] = |
13 static const OperatorInfo g_Operators[] = |
| 14 { |
14 { |
| 15 {TK_ExclamationMark, 0, 1, DH_NegateLogical, }, |
15 {Token::ExclamationMark, 0, 1, DataHeader::NegateLogical, }, |
| 16 {TK_Minus, 0, 1, DH_UnaryMinus, }, |
16 {Token::Minus, 0, 1, DataHeader::UnaryMinus, }, |
| 17 {TK_Multiply, 10, 2, DH_Multiply, }, |
17 {Token::Multiply, 10, 2, DataHeader::Multiply, }, |
| 18 {TK_Divide, 10, 2, DH_Divide, }, |
18 {Token::Divide, 10, 2, DataHeader::Divide, }, |
| 19 {TK_Modulus, 10, 2, DH_Modulus, }, |
19 {Token::Modulus, 10, 2, DataHeader::Modulus, }, |
| 20 {TK_Plus, 20, 2, DH_Add, }, |
20 {Token::Plus, 20, 2, DataHeader::Add, }, |
| 21 {TK_Minus, 20, 2, DH_Subtract, }, |
21 {Token::Minus, 20, 2, DataHeader::Subtract, }, |
| 22 {TK_LeftShift, 30, 2, DH_LeftShift, }, |
22 {Token::LeftShift, 30, 2, DataHeader::LeftShift, }, |
| 23 {TK_RightShift, 30, 2, DH_RightShift, }, |
23 {Token::RightShift, 30, 2, DataHeader::RightShift, }, |
| 24 {TK_Lesser, 40, 2, DH_LessThan, }, |
24 {Token::Lesser, 40, 2, DataHeader::LessThan, }, |
| 25 {TK_Greater, 40, 2, DH_GreaterThan, }, |
25 {Token::Greater, 40, 2, DataHeader::GreaterThan, }, |
| 26 {TK_AtLeast, 40, 2, DH_AtLeast, }, |
26 {Token::AtLeast, 40, 2, DataHeader::AtLeast, }, |
| 27 {TK_AtMost, 40, 2, DH_AtMost, }, |
27 {Token::AtMost, 40, 2, DataHeader::AtMost, }, |
| 28 {TK_Equals, 50, 2, DH_Equals }, |
28 {Token::Equals, 50, 2, DataHeader::Equals }, |
| 29 {TK_NotEquals, 50, 2, DH_NotEquals }, |
29 {Token::NotEquals, 50, 2, DataHeader::NotEquals }, |
| 30 {TK_Amperstand, 60, 2, DH_AndBitwise }, |
30 {Token::Amperstand, 60, 2, DataHeader::AndBitwise }, |
| 31 {TK_Caret, 70, 2, DH_EorBitwise }, |
31 {Token::Caret, 70, 2, DataHeader::EorBitwise }, |
| 32 {TK_Bar, 80, 2, DH_OrBitwise }, |
32 {Token::Bar, 80, 2, DataHeader::OrBitwise }, |
| 33 {TK_DoubleAmperstand, 90, 2, DH_AndLogical }, |
33 {Token::DoubleAmperstand, 90, 2, DataHeader::AndLogical }, |
| 34 {TK_DoubleBar, 100, 2, DH_OrLogical }, |
34 {Token::DoubleBar, 100, 2, DataHeader::OrLogical }, |
| 35 {TK_QuestionMark, 110, 3, (DataHeader) 0 }, |
35 {Token::QuestionMark, 110, 3, DataHeader::NumDataHeaders }, |
| 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 m_parser (parser), |
41 m_parser (parser), |
| 42 m_lexer (lx), |
42 m_lexer (lx), |
| 43 m_type (reqtype) |
43 m_type (reqtype) |
| 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 : m_symbols) |
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 operator or operand or a colon) |
71 // Try to parse an expression symbol (i.e. an operator or operand 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 = m_lexer->position(); |
76 int pos = m_lexer->position(); |
| 77 ExpressionValue* op = null; |
77 ExpressionValue* op = null; |
| 78 |
78 |
| 79 if (m_lexer->next (TK_Colon)) |
79 if (m_lexer->next (Token::Colon)) |
| 80 return new ExpressionColon; |
80 return new ExpressionColon; |
| 81 |
81 |
| 82 // Check for operator |
82 // Check for operator |
| 83 for (const OperatorInfo& op : g_Operators) |
83 for (const OperatorInfo& op : g_Operators) |
| |
84 { |
| 84 if (m_lexer->next (op.token)) |
85 if (m_lexer->next (op.token)) |
| 85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0])); |
86 return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0])); |
| |
87 } |
| 86 |
88 |
| 87 // Check sub-expression |
89 // Check sub-expression |
| 88 if (m_lexer->next (TK_ParenStart)) |
90 if (m_lexer->next (Token::ParenStart)) |
| 89 { |
91 { |
| 90 Expression expr (m_parser, m_lexer, m_type); |
92 Expression expr (m_parser, m_lexer, m_type); |
| 91 m_lexer->mustGetNext (TK_ParenEnd); |
93 m_lexer->mustGetNext (Token::ParenEnd); |
| 92 return expr.getResult()->clone(); |
94 return expr.getResult()->clone(); |
| 93 } |
95 } |
| 94 |
96 |
| 95 op = new ExpressionValue (m_type); |
97 op = new ExpressionValue (m_type); |
| 96 |
98 |
| 97 // Check function |
99 // Check function |
| 98 if (CommandInfo* comm = findCommandByName (m_lexer->peekNextString())) |
100 if (CommandInfo* comm = findCommandByName (m_lexer->peekNextString())) |
| 99 { |
101 { |
| 100 m_lexer->skip(); |
102 m_lexer->skip(); |
| 101 |
103 |
| 102 if (m_type != TYPE_Unknown && comm->returnvalue != m_type) |
104 if (m_type != TYPE_Unknown and comm->returnvalue != m_type) |
| 103 error ("%1 returns an incompatible data type", comm->name); |
105 error ("%1 returns an incompatible data type", comm->name); |
| 104 |
106 |
| 105 op->setBuffer (m_parser->parseCommand (comm)); |
107 op->setBuffer (m_parser->parseCommand (comm)); |
| 106 return op; |
108 return op; |
| 107 } |
109 } |
| 108 |
110 |
| 109 // Check for variables |
111 // Check for variables |
| 110 if (m_lexer->next (TK_DollarSign)) |
112 if (m_lexer->next (Token::DollarSign)) |
| 111 { |
113 { |
| 112 m_lexer->mustGetNext (TK_Symbol); |
114 m_lexer->mustGetNext (Token::Symbol); |
| 113 Variable* var = m_parser->findVariable (getTokenString()); |
115 Variable* var = m_parser->findVariable (getTokenString()); |
| 114 |
116 |
| 115 if (var == null) |
117 if (var == null) |
| 116 error ("unknown variable %1", getTokenString()); |
118 error ("unknown variable %1", getTokenString()); |
| 117 |
119 |
| 118 if (var->type != m_type) |
120 if (var->type != m_type) |
| |
121 { |
| 119 error ("expression requires %1, variable $%2 is of type %3", |
122 error ("expression requires %1, variable $%2 is of type %3", |
| 120 dataTypeName (m_type), var->name, dataTypeName (var->type)); |
123 dataTypeName (m_type), var->name, dataTypeName (var->type)); |
| |
124 } |
| 121 |
125 |
| 122 if (var->isarray) |
126 if (var->isarray) |
| 123 { |
127 { |
| 124 m_lexer->mustGetNext (TK_BracketStart); |
128 m_lexer->mustGetNext (Token::BracketStart); |
| 125 Expression expr (m_parser, m_lexer, TYPE_Int); |
129 Expression expr (m_parser, m_lexer, TYPE_Int); |
| 126 expr.getResult()->convertToBuffer(); |
130 expr.getResult()->convertToBuffer(); |
| 127 DataBuffer* buf = expr.getResult()->buffer()->clone(); |
131 DataBuffer* buf = expr.getResult()->buffer()->clone(); |
| 128 buf->writeDWord (DH_PushGlobalArray); |
132 buf->writeDWord (DataHeader::PushGlobalArray); |
| 129 buf->writeDWord (var->index); |
133 buf->writeDWord (var->index); |
| 130 op->setBuffer (buf); |
134 op->setBuffer (buf); |
| 131 m_lexer->mustGetNext (TK_BracketEnd); |
135 m_lexer->mustGetNext (Token::BracketEnd); |
| 132 } |
136 } |
| 133 elif (var->writelevel == WRITE_Constexpr) |
137 elif (var->writelevel == WRITE_Constexpr) |
| |
138 { |
| 134 op->setValue (var->value); |
139 op->setValue (var->value); |
| |
140 } |
| 135 else |
141 else |
| 136 { |
142 { |
| 137 DataBuffer* buf = new DataBuffer (8); |
143 DataBuffer* buf = new DataBuffer (8); |
| 138 |
144 |
| 139 if (var->IsGlobal()) |
145 if (var->isGlobal()) |
| 140 buf->writeDWord (DH_PushGlobalVar); |
146 buf->writeDWord (DataHeader::PushGlobalVar); |
| 141 else |
147 else |
| 142 buf->writeDWord (DH_PushLocalVar); |
148 buf->writeDWord (DataHeader::PushLocalVar); |
| 143 |
149 |
| 144 buf->writeDWord (var->index); |
150 buf->writeDWord (var->index); |
| 145 op->setBuffer (buf); |
151 op->setBuffer (buf); |
| 146 } |
152 } |
| 147 |
153 |
| 379 } |
388 } |
| 380 |
389 |
| 381 return best; |
390 return best; |
| 382 } |
391 } |
| 383 |
392 |
| 384 // ============================================================================= |
393 // ------------------------------------------------------------------------------------------------- |
| 385 // |
394 // |
| 386 // Process the given operator and values into a new value. |
395 // Process the given operator and values into a new value. |
| 387 // |
396 // |
| 388 ExpressionValue* Expression::evaluateOperator (const ExpressionOperator* op, |
397 ExpressionValue* Expression::evaluateOperator (const ExpressionOperator* op, |
| 389 const List<ExpressionValue*>& values) |
398 const List<ExpressionValue*>& values) |
| 390 { |
399 { |
| 391 const OperatorInfo* info = &g_Operators[op->id()]; |
400 const OperatorInfo* info = &g_Operators[op->id()]; |
| 392 bool isconstexpr = true; |
401 bool isconstexpr = true; |
| 393 ASSERT_EQ (values.size(), info->numoperands) |
402 ASSERT_EQ (values.size(), info->numoperands) |
| 394 |
403 |
| |
404 // See whether the values are constexpr |
| 395 for (ExpressionValue* val : values) |
405 for (ExpressionValue* val : values) |
| 396 { |
406 { |
| 397 if (val->isConstexpr() == false) |
407 if (not val->isConstexpr()) |
| 398 { |
408 { |
| 399 isconstexpr = false; |
409 isconstexpr = false; |
| 400 break; |
410 break; |
| 401 } |
411 } |
| 402 } |
412 } |
| 403 |
413 |
| 404 // If not all of the values are constant expressions, none of them shall be. |
414 // If not all of the values are constexpr, none of them shall be. |
| 405 if (isconstexpr == false) |
415 if (not isconstexpr) |
| |
416 { |
| 406 for (ExpressionValue* val : values) |
417 for (ExpressionValue* val : values) |
| 407 val->convertToBuffer(); |
418 val->convertToBuffer(); |
| |
419 } |
| 408 |
420 |
| 409 ExpressionValue* newval = new ExpressionValue (m_type); |
421 ExpressionValue* newval = new ExpressionValue (m_type); |
| 410 |
422 |
| 411 if (isconstexpr == false) |
423 if (isconstexpr == false) |
| 412 { |
424 { |
| 415 // until Zandronum processes it at run-time. |
427 // until Zandronum processes it at run-time. |
| 416 newval->setBuffer (new DataBuffer); |
428 newval->setBuffer (new DataBuffer); |
| 417 |
429 |
| 418 if (op->id() == OPER_Ternary) |
430 if (op->id() == OPER_Ternary) |
| 419 { |
431 { |
| 420 // There isn't a dataheader for ternary operator. Instead, we use DH_IfNotGoto |
432 // There isn't a dataheader for ternary operator. Instead, we use DataHeader::IfNotGoto |
| 421 // to create an "if-block" inside an expression. |
433 // to create an "if-block" inside an expression. Behold, big block of writing madness! |
| 422 // Behold, big block of writing madness! :P |
|
| 423 // |
|
| 424 DataBuffer* buf = newval->buffer(); |
434 DataBuffer* buf = newval->buffer(); |
| 425 DataBuffer* b0 = values[0]->buffer(); |
435 DataBuffer* b0 = values[0]->buffer(); |
| 426 DataBuffer* b1 = values[1]->buffer(); |
436 DataBuffer* b1 = values[1]->buffer(); |
| 427 DataBuffer* b2 = values[2]->buffer(); |
437 DataBuffer* b2 = values[2]->buffer(); |
| 428 ByteMark* mark1 = buf->addMark (""); // start of "else" case |
438 ByteMark* mark1 = buf->addMark (""); // start of "else" case |
| 429 ByteMark* mark2 = buf->addMark (""); // end of expression |
439 ByteMark* mark2 = buf->addMark (""); // end of expression |
| 430 buf->mergeAndDestroy (b0); |
440 buf->mergeAndDestroy (b0); |
| 431 buf->writeDWord (DH_IfNotGoto); // if the first operand (condition) |
441 buf->writeDWord (DataHeader::IfNotGoto); // if the first operand (condition) |
| 432 buf->addReference (mark1); // didn't eval true, jump into mark1 |
442 buf->addReference (mark1); // didn't eval true, jump into mark1 |
| 433 buf->mergeAndDestroy (b1); // otherwise, perform second operand (true case) |
443 buf->mergeAndDestroy (b1); // otherwise, perform second operand (true case) |
| 434 buf->writeDWord (DH_Goto); // afterwards, jump to the end, which is |
444 buf->writeDWord (DataHeader::Goto); // afterwards, jump to the end, which is |
| 435 buf->addReference (mark2); // marked by mark2. |
445 buf->addReference (mark2); // marked by mark2. |
| 436 buf->adjustMark (mark1); // move mark1 at the end of the true case |
446 buf->adjustMark (mark1); // move mark1 at the end of the true case |
| 437 buf->mergeAndDestroy (b2); // perform third operand (false case) |
447 buf->mergeAndDestroy (b2); // perform third operand (false case) |
| 438 buf->adjustMark (mark2); // move the ending mark2 here |
448 buf->adjustMark (mark2); // move the ending mark2 here |
| 439 |
449 |
| 440 for (int i = 0; i < 3; ++i) |
450 for (int i = 0; i < 3; ++i) |
| 441 values[i]->setBuffer (null); |
451 values[i]->setBuffer (null); |
| 442 } |
452 } |
| 443 else |
453 else |
| 444 { |
454 { |
| |
455 ASSERT_NE (info->header, DataHeader::NumDataHeaders); |
| |
456 |
| 445 // Generic case: write all arguments and apply the operator's |
457 // Generic case: write all arguments and apply the operator's |
| 446 // data header. |
458 // data header. |
| 447 for (ExpressionValue* val : values) |
459 for (ExpressionValue* val : values) |
| 448 { |
460 { |
| 449 newval->buffer()->mergeAndDestroy (val->buffer()); |
461 newval->buffer()->mergeAndDestroy (val->buffer()); |
| 583 ASSERT_EQ (m_symbols.first()->type(), EXPRSYM_Value) |
595 ASSERT_EQ (m_symbols.first()->type(), EXPRSYM_Value) |
| 584 ExpressionValue* val = static_cast<ExpressionValue*> (m_symbols.first()); |
596 ExpressionValue* val = static_cast<ExpressionValue*> (m_symbols.first()); |
| 585 return val; |
597 return val; |
| 586 } |
598 } |
| 587 |
599 |
| 588 // ============================================================================= |
600 // ------------------------------------------------------------------------------------------------- |
| 589 // |
601 // |
| 590 ExpressionValue* Expression::getResult() |
602 ExpressionValue* Expression::getResult() |
| 591 { |
603 { |
| 592 return static_cast<ExpressionValue*> (m_symbols.first()); |
604 return static_cast<ExpressionValue*> (m_symbols.first()); |
| 593 } |
605 } |
| 594 |
606 |
| 595 // ============================================================================= |
607 // ------------------------------------------------------------------------------------------------- |
| 596 // |
608 // |
| 597 String Expression::getTokenString() |
609 String Expression::getTokenString() |
| 598 { |
610 { |
| 599 return m_lexer->token()->text; |
611 return m_lexer->token()->text; |
| 600 } |
612 } |
| 601 |
613 |
| 602 // ============================================================================= |
614 // ------------------------------------------------------------------------------------------------- |
| 603 // |
615 // |
| 604 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
616 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
| 605 ExpressionSymbol (EXPRSYM_Operator), |
617 ExpressionSymbol (EXPRSYM_Operator), |
| 606 m_id (id) {} |
618 m_id (id) {} |
| 607 |
619 |
| 608 // ============================================================================= |
620 // ------------------------------------------------------------------------------------------------- |
| 609 // |
621 // |
| 610 ExpressionValue::ExpressionValue (DataType valuetype) : |
622 ExpressionValue::ExpressionValue (DataType valuetype) : |
| 611 ExpressionSymbol (EXPRSYM_Value), |
623 ExpressionSymbol (EXPRSYM_Value), |
| 612 m_buffer (null), |
624 m_buffer (null), |
| 613 m_valueType (valuetype) {} |
625 m_valueType (valuetype) {} |
| 614 |
626 |
| 615 // ============================================================================= |
627 // ------------------------------------------------------------------------------------------------- |
| 616 // |
628 // |
| 617 ExpressionValue::~ExpressionValue() |
629 ExpressionValue::~ExpressionValue() |
| 618 { |
630 { |
| 619 delete m_buffer; |
631 delete m_buffer; |
| 620 } |
632 } |
| 621 |
633 |
| 622 // ============================================================================= |
634 // ------------------------------------------------------------------------------------------------- |
| 623 // |
635 // |
| 624 void ExpressionValue::convertToBuffer() |
636 void ExpressionValue::convertToBuffer() |
| 625 { |
637 { |
| 626 if (isConstexpr() == false) |
638 if (isConstexpr() == false) |
| 627 return; |
639 return; |