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; |