| 129 // Must end in a colon |
129 // Must end in a colon |
| 130 m_lx->must_get_next (tk_colon); |
130 m_lx->must_get_next (tk_colon); |
| 131 |
131 |
| 132 // write the previous state's onenter and |
132 // write the previous state's onenter and |
| 133 // mainloop buffers to file now |
133 // mainloop buffers to file now |
| 134 if (g_CurState.len()) |
134 if (g_CurState.is_empty() == false) |
| 135 w->write (Buffers(); |
135 w->write_member_buffers(); |
| 136 |
136 |
| 137 w->write (DH_STATENAME); |
137 w->write (dh_state_name); |
| 138 w->write_string (statename); |
138 w->write_string (statename); |
| 139 w->write (DH_STATEIDX); |
139 w->write (dh_state_index); |
| 140 w->write (g_NumStates); |
140 w->write (g_NumStates); |
| 141 |
141 |
| 142 g_NumStates++; |
142 g_NumStates++; |
| 143 g_CurState = TOKEN; |
143 g_CurState = TOKEN; |
| 144 g_GotMainLoop = false; |
144 g_GotMainLoop = false; |
| 190 m_lx->must_get_next (tk_brace_start); |
190 m_lx->must_get_next (tk_brace_start); |
| 191 |
191 |
| 192 // Mode must be set before dataheader is written here, |
192 // Mode must be set before dataheader is written here, |
| 193 // because onenter goes to a separate buffer. |
193 // because onenter goes to a separate buffer. |
| 194 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
194 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; |
| 195 w->write (onenter ? DH_ONENTER : DH_ONEXIT); |
195 w->write (onenter ? dh_on_enter : dh_on_exit); |
| 196 } |
196 } |
| 197 break; |
197 break; |
| 198 |
198 |
| 199 // ============================================================ |
199 // ============================================================ |
| 200 // |
200 // |
| 204 { |
204 { |
| 205 // For now, only globals are supported |
205 // For now, only globals are supported |
| 206 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) |
206 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) |
| 207 error ("variables must only be global for now"); |
207 error ("variables must only be global for now"); |
| 208 |
208 |
| 209 type_e type = (TOKEN == "int") ? TYPE_INT : |
209 type_e type = (token_is (tk_int)) ? TYPE_INT : |
| 210 (TOKEN == "str") ? TYPE_STRING : |
210 (token_is (tk_str)) ? TYPE_STRING : |
| 211 TYPE_BOOL; |
211 TYPE_BOOL; |
| 212 |
212 |
| 213 m_lx->must_get_next(); |
213 m_lx->must_get_next(); |
| 214 |
214 |
| 215 // Var name must not be a number |
215 // Var name must not be a number |
| 216 if (TOKEN.is_numeric()) |
216 if (TOKEN.is_numeric()) |
| 217 error ("variable name must not be a number"); |
217 error ("variable name must not be a number"); |
| 218 |
218 |
| 219 string varname = TOKEN; |
219 string varname = TOKEN; |
| 220 script_variable* var = DeclareGlobalVariable (this, type, varname); |
220 script_variable* var = declare_global_variable (this, type, varname); |
| 221 m_lx->must_get_next (tk_semicolon); |
221 m_lx->must_get_next (tk_semicolon); |
| 222 } |
222 } |
| 223 break; |
223 break; |
| 224 |
224 |
| 225 // ============================================================ |
225 // ============================================================ |
| 268 |
268 |
| 269 // Add a mark - to here temporarily - and add a reference to it. |
269 // Add a mark - to here temporarily - and add a reference to it. |
| 270 // Upon a closing brace, the mark will be adjusted. |
270 // Upon a closing brace, the mark will be adjusted. |
| 271 int marknum = w->add_mark (""); |
271 int marknum = w->add_mark (""); |
| 272 |
272 |
| 273 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark |
273 // Use dh_if_not_goto - if the expression is not true, we goto the mark |
| 274 // we just defined - and this mark will be at the end of the scope block. |
274 // we just defined - and this mark will be at the end of the scope block. |
| 275 w->write (DH_IFNOTGOTO); |
275 w->write (dh_if_not_goto); |
| 276 w->add_reference (marknum); |
276 w->add_reference (marknum); |
| 277 |
277 |
| 278 // Store it |
278 // Store it |
| 279 SCOPE (0).mark1 = marknum; |
279 SCOPE (0).mark1 = marknum; |
| 280 SCOPE (0).type = SCOPETYPE_IF; |
280 SCOPE (0).type = e_if_scope; |
| 281 } break; |
281 } break; |
| 282 |
282 |
| 283 // ============================================================ |
283 // ============================================================ |
| 284 // |
284 // |
| 285 case tk_else: |
285 case tk_else: |
| 291 g_ScopeCursor++; |
291 g_ScopeCursor++; |
| 292 |
292 |
| 293 if (g_ScopeCursor >= MAX_SCOPE) |
293 if (g_ScopeCursor >= MAX_SCOPE) |
| 294 error ("too deep scope"); |
294 error ("too deep scope"); |
| 295 |
295 |
| 296 if (SCOPE (0).type != SCOPETYPE_IF) |
296 if (SCOPE (0).type != e_if_scope) |
| 297 error ("else without preceding if"); |
297 error ("else without preceding if"); |
| 298 |
298 |
| 299 // write down to jump to the end of the else statement |
299 // write down to jump to the end of the else statement |
| 300 // Otherwise we have fall-throughs |
300 // Otherwise we have fall-throughs |
| 301 SCOPE (0).mark2 = w->add_mark (""); |
301 SCOPE (0).mark2 = w->add_mark (""); |
| 302 |
302 |
| 303 // Instruction to jump to the end after if block is complete |
303 // Instruction to jump to the end after if block is complete |
| 304 w->write (DH_GOTO); |
304 w->write (dh_goto); |
| 305 w->add_reference (SCOPE (0).mark2); |
305 w->add_reference (SCOPE (0).mark2); |
| 306 |
306 |
| 307 // Move the ifnot mark here and set type to else |
307 // Move the ifnot mark here and set type to else |
| 308 w->move_mark (SCOPE (0).mark1); |
308 w->move_mark (SCOPE (0).mark1); |
| 309 SCOPE (0).type = SCOPETYPE_ELSE; |
309 SCOPE (0).type = e_else_scope; |
| 310 } |
310 } |
| 311 break; |
311 break; |
| 312 |
312 |
| 313 // ============================================================ |
313 // ============================================================ |
| 314 // |
314 // |
| 333 |
333 |
| 334 // write condition |
334 // write condition |
| 335 w->write_buffer (expr); |
335 w->write_buffer (expr); |
| 336 |
336 |
| 337 // Instruction to go to the end if it fails |
337 // Instruction to go to the end if it fails |
| 338 w->write (DH_IFNOTGOTO); |
338 w->write (dh_if_not_goto); |
| 339 w->add_reference (mark2); |
339 w->add_reference (mark2); |
| 340 |
340 |
| 341 // Store the needed stuff |
341 // Store the needed stuff |
| 342 SCOPE (0).mark1 = mark1; |
342 SCOPE (0).mark1 = mark1; |
| 343 SCOPE (0).mark2 = mark2; |
343 SCOPE (0).mark2 = mark2; |
| 344 SCOPE (0).type = SCOPETYPE_WHILE; |
344 SCOPE (0).type = e_while_scope; |
| 345 } |
345 } |
| 346 break; |
346 break; |
| 347 |
347 |
| 348 // ============================================================ |
348 // ============================================================ |
| 349 // |
349 // |
| 388 int mark1 = w->add_mark (""); |
388 int mark1 = w->add_mark (""); |
| 389 int mark2 = w->add_mark (""); |
389 int mark2 = w->add_mark (""); |
| 390 |
390 |
| 391 // Add the condition |
391 // Add the condition |
| 392 w->write_buffer (cond); |
392 w->write_buffer (cond); |
| 393 w->write (DH_IFNOTGOTO); |
393 w->write (dh_if_not_goto); |
| 394 w->add_reference (mark2); |
394 w->add_reference (mark2); |
| 395 |
395 |
| 396 // Store the marks and incrementor |
396 // Store the marks and incrementor |
| 397 SCOPE (0).mark1 = mark1; |
397 SCOPE (0).mark1 = mark1; |
| 398 SCOPE (0).mark2 = mark2; |
398 SCOPE (0).mark2 = mark2; |
| 399 SCOPE (0).buffer1 = incr; |
399 SCOPE (0).buffer1 = incr; |
| 400 SCOPE (0).type = SCOPETYPE_FOR; |
400 SCOPE (0).type = e_for_scope; |
| 401 } |
401 } |
| 402 break; |
402 break; |
| 403 |
403 |
| 404 // ============================================================ |
404 // ============================================================ |
| 405 // |
405 // |
| 435 m_lx->must_get_next (tk_paren_start); |
435 m_lx->must_get_next (tk_paren_start); |
| 436 m_lx->must_get_next(); |
436 m_lx->must_get_next(); |
| 437 w->write_buffer (parse_expression (TYPE_INT)); |
437 w->write_buffer (parse_expression (TYPE_INT)); |
| 438 m_lx->must_get_next (tk_paren_end); |
438 m_lx->must_get_next (tk_paren_end); |
| 439 m_lx->must_get_next (tk_brace_start); |
439 m_lx->must_get_next (tk_brace_start); |
| 440 SCOPE (0).type = SCOPETYPE_SWITCH; |
440 SCOPE (0).type = e_switch_scope; |
| 441 SCOPE (0).mark1 = w->add_mark (""); // end mark |
441 SCOPE (0).mark1 = w->add_mark (""); // end mark |
| 442 SCOPE (0).buffer1 = null; // default header |
442 SCOPE (0).buffer1 = null; // default header |
| 443 } |
443 } |
| 444 break; |
444 break; |
| 445 |
445 |
| 446 // ============================================================ |
446 // ============================================================ |
| 447 // |
447 // |
| 448 case tk_case: |
448 case tk_case: |
| 449 { |
449 { |
| 450 // case is only allowed inside switch |
450 // case is only allowed inside switch |
| 451 if (SCOPE (0).type != SCOPETYPE_SWITCH) |
451 if (SCOPE (0).type != e_switch_scope) |
| 452 error ("case label outside switch"); |
452 error ("case label outside switch"); |
| 453 |
453 |
| 454 // Get the literal (Zandronum does not support expressions here) |
454 // Get the literal (Zandronum does not support expressions here) |
| 455 m_lx->must_get_next (tk_number); |
455 m_lx->must_get_next (tk_number); |
| 456 int num = m_lx->get_token()->text.to_long(); |
456 int num = m_lx->get_token()->text.to_long(); |
| 467 // for the case block that this heralds, and takes care |
467 // for the case block that this heralds, and takes care |
| 468 // of buffering setup and stuff like that. |
468 // of buffering setup and stuff like that. |
| 469 // null the switch buffer for the case-go-to statement, |
469 // null the switch buffer for the case-go-to statement, |
| 470 // we want it all under the switch, not into the case-buffers. |
470 // we want it all under the switch, not into the case-buffers. |
| 471 w->SwitchBuffer = null; |
471 w->SwitchBuffer = null; |
| 472 w->write (DH_CASEGOTO); |
472 w->write (dh_case_goto); |
| 473 w->write (num); |
473 w->write (num); |
| 474 add_switch_case (w, null); |
474 add_switch_case (w, null); |
| 475 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num; |
475 SCOPE (0).casenumbers[SCOPE (0).casecursor] = num; |
| 476 } |
476 } |
| 477 break; |
477 break; |
| 478 |
478 |
| 479 // ============================================================ |
479 // ============================================================ |
| 480 // |
480 // |
| 481 case tk_default: |
481 case tk_default: |
| 482 { |
482 { |
| 483 if (SCOPE (0).type != SCOPETYPE_SWITCH) |
483 if (SCOPE (0).type != e_switch_scope) |
| 484 error ("default label outside switch"); |
484 error ("default label outside switch"); |
| 485 |
485 |
| 486 if (SCOPE (0).buffer1) |
486 if (SCOPE (0).buffer1) |
| 487 error ("multiple default labels in one switch"); |
487 error ("multiple default labels in one switch"); |
| 488 |
488 |
| 491 // The default header is buffered into buffer1, since |
491 // The default header is buffered into buffer1, since |
| 492 // it has to be the last of the case headers |
492 // it has to be the last of the case headers |
| 493 // |
493 // |
| 494 // Since the expression is pushed into the switch |
494 // Since the expression is pushed into the switch |
| 495 // and is only popped when case succeeds, we have |
495 // and is only popped when case succeeds, we have |
| 496 // to pop it with DH_DROP manually if we end up in |
496 // to pop it with dh_drop manually if we end up in |
| 497 // a default. |
497 // a default. |
| 498 data_buffer* b = new data_buffer; |
498 data_buffer* b = new data_buffer; |
| 499 SCOPE (0).buffer1 = b; |
499 SCOPE (0).buffer1 = b; |
| 500 b->write (DH_DROP); |
500 b->write (dh_drop); |
| 501 b->write (DH_GOTO); |
501 b->write (dh_goto); |
| 502 add_switch_case (w, b); |
502 add_switch_case (w, b); |
| 503 } |
503 } |
| 504 break; |
504 break; |
| 505 |
505 |
| 506 // ============================================================ |
506 // ============================================================ |
| 508 case tk_break: |
508 case tk_break: |
| 509 { |
509 { |
| 510 if (!g_ScopeCursor) |
510 if (!g_ScopeCursor) |
| 511 error ("unexpected `break`"); |
511 error ("unexpected `break`"); |
| 512 |
512 |
| 513 w->write (DH_GOTO); |
513 w->write (dh_goto); |
| 514 |
514 |
| 515 // switch and if use mark1 for the closing point, |
515 // switch and if use mark1 for the closing point, |
| 516 // for and while use mark2. |
516 // for and while use mark2. |
| 517 switch (SCOPE (0).type) |
517 switch (SCOPE (0).type) |
| 518 { |
518 { |
| 519 case SCOPETYPE_IF: |
519 case e_if_scope: |
| 520 case SCOPETYPE_SWITCH: |
520 case e_switch_scope: |
| 521 { |
521 { |
| 522 w->add_reference (SCOPE (0).mark1); |
522 w->add_reference (SCOPE (0).mark1); |
| 523 } break; |
523 } break; |
| 524 |
524 |
| 525 case SCOPETYPE_FOR: |
525 case e_for_scope: |
| 526 case SCOPETYPE_WHILE: |
526 case e_while_scope: |
| 527 { |
527 { |
| 528 w->add_reference (SCOPE (0).mark2); |
528 w->add_reference (SCOPE (0).mark2); |
| 529 } break; |
529 } break; |
| 530 |
530 |
| 531 default: |
531 default: |
| 578 // If we're in the block stack, we're descending down from it now |
578 // If we're in the block stack, we're descending down from it now |
| 579 if (g_ScopeCursor > 0) |
579 if (g_ScopeCursor > 0) |
| 580 { |
580 { |
| 581 switch (SCOPE (0).type) |
581 switch (SCOPE (0).type) |
| 582 { |
582 { |
| 583 case SCOPETYPE_IF: |
583 case e_if_scope: |
| 584 // Adjust the closing mark. |
584 // Adjust the closing mark. |
| 585 w->move_mark (SCOPE (0).mark1); |
585 w->move_mark (SCOPE (0).mark1); |
| 586 |
586 |
| 587 // We're returning from if, thus else can be next |
587 // We're returning from if, thus else can be next |
| 588 g_CanElse = true; |
588 g_CanElse = true; |
| 589 break; |
589 break; |
| 590 |
590 |
| 591 case SCOPETYPE_ELSE: |
591 case e_else_scope: |
| 592 // else instead uses mark1 for itself (so if expression |
592 // else instead uses mark1 for itself (so if expression |
| 593 // fails, jump to else), mark2 means end of else |
593 // fails, jump to else), mark2 means end of else |
| 594 w->move_mark (SCOPE (0).mark2); |
594 w->move_mark (SCOPE (0).mark2); |
| 595 break; |
595 break; |
| 596 |
596 |
| 597 case SCOPETYPE_FOR: |
597 case e_for_scope: |
| 598 // write the incrementor at the end of the loop block |
598 // write the incrementor at the end of the loop block |
| 599 w->write_buffer (SCOPE (0).buffer1); |
599 w->write_buffer (SCOPE (0).buffer1); |
| 600 |
600 |
| 601 // fall-thru |
601 // fall-thru |
| 602 case SCOPETYPE_WHILE: |
602 case e_while_scope: |
| 603 // write down the instruction to go back to the start of the loop |
603 // write down the instruction to go back to the start of the loop |
| 604 w->write (DH_GOTO); |
604 w->write (dh_goto); |
| 605 w->add_reference (SCOPE (0).mark1); |
605 w->add_reference (SCOPE (0).mark1); |
| 606 |
606 |
| 607 // Move the closing mark here since we're at the end of the while loop |
607 // Move the closing mark here since we're at the end of the while loop |
| 608 w->move_mark (SCOPE (0).mark2); |
608 w->move_mark (SCOPE (0).mark2); |
| 609 break; |
609 break; |
| 610 |
610 |
| 611 case SCOPETYPE_DO: |
611 case e_do_scope: |
| 612 { |
612 { |
| 613 must_get_next (tk_while); |
613 m_lx->must_get_next (tk_while); |
| 614 m_lx->must_get_next (tk_paren_start); |
614 m_lx->must_get_next (tk_paren_start); |
| 615 m_lx->must_get_next(); |
615 m_lx->must_get_next(); |
| 616 data_buffer* expr = parse_expression (TYPE_INT); |
616 data_buffer* expr = parse_expression (TYPE_INT); |
| 617 m_lx->must_get_next (tk_paren_end); |
617 m_lx->must_get_next (tk_paren_end); |
| 618 m_lx->must_get_next (tk_semicolon); |
618 m_lx->must_get_next (tk_semicolon); |
| 619 |
619 |
| 620 // If the condition runs true, go back to the start. |
620 // If the condition runs true, go back to the start. |
| 621 w->write_buffer (expr); |
621 w->write_buffer (expr); |
| 622 w->write (DH_IFGOTO); |
622 w->write (dh_if_goto); |
| 623 w->add_reference (SCOPE (0).mark1); |
623 w->add_reference (SCOPE (0).mark1); |
| 624 break; |
624 break; |
| 625 } |
625 } |
| 626 |
626 |
| 627 case SCOPETYPE_SWITCH: |
627 case e_switch_scope: |
| 628 { |
628 { |
| 629 // Switch closes. Move down to the record buffer of |
629 // Switch closes. Move down to the record buffer of |
| 630 // the lower block. |
630 // the lower block. |
| 631 if (SCOPE (1).casecursor != -1) |
631 if (SCOPE (1).casecursor != -1) |
| 632 w->SwitchBuffer = SCOPE (1).casebuffers[SCOPE (1).casecursor]; |
632 w->SwitchBuffer = SCOPE (1).casebuffers[SCOPE (1).casecursor]; |
| 659 // Move the closing mark here |
659 // Move the closing mark here |
| 660 w->move_mark (SCOPE (0).mark1); |
660 w->move_mark (SCOPE (0).mark1); |
| 661 break; |
661 break; |
| 662 } |
662 } |
| 663 |
663 |
| 664 case SCOPETYPE_UNKNOWN: |
664 case e_unknown_scope: |
| 665 break; |
665 break; |
| 666 } |
666 } |
| 667 |
667 |
| 668 // Descend down the stack |
668 // Descend down the stack |
| 669 g_ScopeCursor--; |
669 g_ScopeCursor--; |
| 670 continue; |
670 continue; |
| 671 } |
671 } |
| 672 |
672 |
| 673 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : |
673 int dataheader = (g_CurMode == MODE_EVENT) ? dh_end_event : |
| 674 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : |
674 (g_CurMode == MODE_MAINLOOP) ? dh_end_main_loop : |
| 675 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : |
675 (g_CurMode == MODE_ONENTER) ? dh_end_on_enter : |
| 676 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; |
676 (g_CurMode == MODE_ONEXIT) ? dh_end_on_exit : -1; |
| 677 |
677 |
| 678 if (dataheader == -1) |
678 if (dataheader == -1) |
| 679 error ("unexpected `}`"); |
679 error ("unexpected `}`"); |
| 680 |
680 |
| 681 // Data header must be written before mode is changed because |
681 // Data header must be written before mode is changed because |
| 682 // onenter and mainloop go into special buffers, and we want |
682 // onenter and mainloop go into special buffers, and we want |
| 683 // the closing data headers into said buffers too. |
683 // the closing data headers into said buffers too. |
| 684 w->write (dataheader); |
684 w->write (dataheader); |
| 685 g_CurMode = MODE_TOPLEVEL; |
685 g_CurMode = MODE_TOPLEVEL; |
| 686 |
686 lexer::token* tok; |
| 687 if (PeekNext() == ";") |
687 m_lx->get_next (tk_semicolon); |
| 688 m_lx->must_get_next (tk_semicolon); |
|
| 689 } |
688 } |
| 690 break; |
689 break; |
| 691 |
690 |
| 692 // ============================================================ |
691 // ============================================================ |
| 693 case tk_const: |
692 case tk_const: |
| 746 |
745 |
| 747 // want no conflicts.. |
746 // want no conflicts.. |
| 748 if (FindCommand (label_name)) |
747 if (FindCommand (label_name)) |
| 749 error ("label name `%s` conflicts with command name\n", label_name); |
748 error ("label name `%s` conflicts with command name\n", label_name); |
| 750 |
749 |
| 751 if (FindGlobalVariable (label_name)) |
750 if (find_global_variable (label_name)) |
| 752 error ("label name `%s` conflicts with variable\n", label_name); |
751 error ("label name `%s` conflicts with variable\n", label_name); |
| 753 |
752 |
| 754 // See if a mark already exists for this label |
753 // See if a mark already exists for this label |
| 755 int mark = -1; |
754 int mark = -1; |
| 756 |
755 |
| 876 } |
875 } |
| 877 |
876 |
| 878 // If the script skipped any optional arguments, fill in defaults. |
877 // If the script skipped any optional arguments, fill in defaults. |
| 879 while (curarg < comm->maxargs) |
878 while (curarg < comm->maxargs) |
| 880 { |
879 { |
| 881 r->write (DH_PUSHNUMBER); |
880 r->write (dh_push_number); |
| 882 r->write (comm->defvals[curarg]); |
881 r->write (comm->defvals[curarg]); |
| 883 curarg++; |
882 curarg++; |
| 884 } |
883 } |
| 885 |
884 |
| 886 r->write (DH_COMMAND); |
885 r->write (dh_command); |
| 887 r->write (comm->number); |
886 r->write (comm->number); |
| 888 r->write (comm->maxargs); |
887 r->write (comm->maxargs); |
| 889 |
888 |
| 890 return r; |
889 return r; |
| 891 } |
890 } |
| 923 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not |
922 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not |
| 924 // have data headers, instead they are expanded out in |
923 // have data headers, instead they are expanded out in |
| 925 // the operator parser |
924 // the operator parser |
| 926 switch (oper) |
925 switch (oper) |
| 927 { |
926 { |
| 928 case OPER_ASSIGNADD: return DH_ADDGLOBALVAR; |
927 case OPER_ASSIGNADD: return dh_add_global_var; |
| 929 case OPER_ASSIGNSUB: return DH_SUBGLOBALVAR; |
928 case OPER_ASSIGNSUB: return dh_subtract_global_var; |
| 930 case OPER_ASSIGNMUL: return DH_MULGLOBALVAR; |
929 case OPER_ASSIGNMUL: return dh_multiply_global_var; |
| 931 case OPER_ASSIGNDIV: return DH_DIVGLOBALVAR; |
930 case OPER_ASSIGNDIV: return dh_divide_global_var; |
| 932 case OPER_ASSIGNMOD: return DH_MODGLOBALVAR; |
931 case OPER_ASSIGNMOD: return dh_mod_global_var; |
| 933 case OPER_ASSIGN: return DH_ASSIGNGLOBALVAR; |
932 case OPER_ASSIGN: return dh_assign_global_var; |
| 934 |
933 |
| 935 default: error ("bad assignment operator!!\n"); |
934 default: error ("bad assignment operator!!\n"); |
| 936 } |
935 } |
| 937 } |
936 } |
| 938 |
937 |
| 939 switch (oper) |
938 switch (oper) |
| 940 { |
939 { |
| 941 case OPER_ADD: return DH_ADD; |
940 case OPER_ADD: return dh_add; |
| 942 case OPER_SUBTRACT: return DH_SUBTRACT; |
941 case OPER_SUBTRACT: return dh_subtract; |
| 943 case OPER_MULTIPLY: return DH_MULTIPLY; |
942 case OPER_MULTIPLY: return dh_multiply; |
| 944 case OPER_DIVIDE: return DH_DIVIDE; |
943 case OPER_DIVIDE: return dh_divide; |
| 945 case OPER_MODULUS: return DH_MODULUS; |
944 case OPER_MODULUS: return dh_modulus; |
| 946 case OPER_EQUALS: return DH_EQUALS; |
945 case OPER_EQUALS: return dh_equals; |
| 947 case OPER_NOTEQUALS: return DH_NOTEQUALS; |
946 case OPER_NOTEQUALS: return dh_not_equals; |
| 948 case OPER_LESSTHAN: return DH_LESSTHAN; |
947 case OPER_LESSTHAN: return dh_less_than; |
| 949 case OPER_GREATERTHAN: return DH_GREATERTHAN; |
948 case OPER_GREATERTHAN: return dh_greater_than; |
| 950 case OPER_LESSTHANEQUALS: return DH_LESSTHANEQUALS; |
949 case OPER_LESSTHANEQUALS: return dh_at_most; |
| 951 case OPER_GREATERTHANEQUALS: return DH_GREATERTHANEQUALS; |
950 case OPER_GREATERTHANEQUALS: return dh_at_least; |
| 952 case OPER_LEFTSHIFT: return DH_LSHIFT; |
951 case OPER_LEFTSHIFT: return dh_left_shift; |
| 953 case OPER_RIGHTSHIFT: return DH_RSHIFT; |
952 case OPER_RIGHTSHIFT: return dh_right_shift; |
| 954 case OPER_OR: return DH_ORLOGICAL; |
953 case OPER_OR: return dh_or_logical; |
| 955 case OPER_AND: return DH_ANDLOGICAL; |
954 case OPER_AND: return dh_and_logical; |
| 956 case OPER_BITWISEOR: return DH_ORBITWISE; |
955 case OPER_BITWISEOR: return dh_or_bitwise; |
| 957 case OPER_BITWISEEOR: return DH_EORBITWISE; |
956 case OPER_BITWISEEOR: return dh_eor_bitwise; |
| 958 case OPER_BITWISEAND: return DH_ANDBITWISE; |
957 case OPER_BITWISEAND: return dh_and_bitwise; |
| 959 } |
958 } |
| 960 |
959 |
| 961 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); |
960 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); |
| 962 return 0; |
961 return 0; |
| 963 } |
962 } |
| 997 // It also is handled differently: there isn't a dataheader for ternary |
996 // It also is handled differently: there isn't a dataheader for ternary |
| 998 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. |
997 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. |
| 999 // Behold, big block of writing madness! :P |
998 // Behold, big block of writing madness! :P |
| 1000 int mark1 = retbuf->add_mark (""); // start of "else" case |
999 int mark1 = retbuf->add_mark (""); // start of "else" case |
| 1001 int mark2 = retbuf->add_mark (""); // end of expression |
1000 int mark2 = retbuf->add_mark (""); // end of expression |
| 1002 retbuf->write (DH_IFNOTGOTO); // if the first operand (condition) |
1001 retbuf->write (dh_if_not_goto); // if the first operand (condition) |
| 1003 retbuf->add_reference (mark1); // didn't eval true, jump into mark1 |
1002 retbuf->add_reference (mark1); // didn't eval true, jump into mark1 |
| 1004 retbuf->merge (rb); // otherwise, perform second operand (true case) |
1003 retbuf->merge (rb); // otherwise, perform second operand (true case) |
| 1005 retbuf->write (DH_GOTO); // afterwards, jump to the end, which is |
1004 retbuf->write (dh_goto); // afterwards, jump to the end, which is |
| 1006 retbuf->add_reference (mark2); // marked by mark2. |
1005 retbuf->add_reference (mark2); // marked by mark2. |
| 1007 retbuf->move_mark (mark1); // move mark1 at the end of the true case |
1006 retbuf->move_mark (mark1); // move mark1 at the end of the true case |
| 1008 retbuf->merge (tb); // perform third operand (false case) |
1007 retbuf->merge (tb); // perform third operand (false case) |
| 1009 retbuf->move_mark (mark2); // move the ending mark2 here |
1008 retbuf->move_mark (mark2); // move the ending mark2 here |
| 1010 } |
1009 } |
| 1055 { |
1054 { |
| 1056 return o; |
1055 return o; |
| 1057 } |
1056 } |
| 1058 |
1057 |
| 1059 // Two-char operators |
1058 // Two-char operators |
| 1060 oper += PeekNext (peek ? 1 : 0); |
1059 oper += m_lx->peek_next_string ( (peek ? 1 : 0); |
| 1061 equalsnext = PeekNext (peek ? 2 : 1) == ("="); |
1060 equalsnext = m_lx->peek_next_string (peek ? 2 : 1) == ("="); |
| 1062 |
1061 |
| 1063 o = (oper == "+=") ? OPER_ASSIGNADD : |
1062 o = (oper == "+=") ? OPER_ASSIGNADD : |
| 1064 (oper == "-=") ? OPER_ASSIGNSUB : |
1063 (oper == "-=") ? OPER_ASSIGNSUB : |
| 1065 (oper == "*=") ? OPER_ASSIGNMUL : |
1064 (oper == "*=") ? OPER_ASSIGNMUL : |
| 1066 (oper == "/=") ? OPER_ASSIGNDIV : |
1065 (oper == "/=") ? OPER_ASSIGNDIV : |
| 1144 error ("strlen only works with const str"); |
1143 error ("strlen only works with const str"); |
| 1145 |
1144 |
| 1146 if (reqtype != TYPE_INT) |
1145 if (reqtype != TYPE_INT) |
| 1147 error ("strlen returns int but %s is expected\n", GetTypeName (reqtype).c_str()); |
1146 error ("strlen returns int but %s is expected\n", GetTypeName (reqtype).c_str()); |
| 1148 |
1147 |
| 1149 b->write (DH_PUSHNUMBER); |
1148 b->write (dh_push_number); |
| 1150 b->write (constant->val.len()); |
1149 b->write (constant->val.len()); |
| 1151 |
1150 |
| 1152 m_lx->must_get_next (tk_paren_end); |
1151 m_lx->must_get_next (tk_paren_end); |
| 1153 } |
1152 } |
| 1154 else if (TOKEN == "(") |
1153 else if (TOKEN == "(") |
| 1215 { |
1214 { |
| 1216 m_lx->must_be (tk_number); |
1215 m_lx->must_be (tk_number); |
| 1217 |
1216 |
| 1218 // All values are written unsigned - thus we need to write the value's |
1217 // All values are written unsigned - thus we need to write the value's |
| 1219 // absolute value, followed by an unary minus for negatives. |
1218 // absolute value, followed by an unary minus for negatives. |
| 1220 b->write (DH_PUSHNUMBER); |
1219 b->write (dh_push_number); |
| 1221 |
1220 |
| 1222 long v = atol (TOKEN); |
1221 long v = atol (TOKEN); |
| 1223 b->write (static_cast<word> (abs (v))); |
1222 b->write (static_cast<word> (abs (v))); |
| 1224 |
1223 |
| 1225 if (v < 0) |
1224 if (v < 0) |
| 1226 b->write (DH_UNARYMINUS); |
1225 b->write (dh_unary_minus); |
| 1227 |
1226 |
| 1228 break; |
1227 break; |
| 1229 } |
1228 } |
| 1230 |
1229 |
| 1231 case TYPE_STRING: |
1230 case TYPE_STRING: |
| 1232 // PushToStringTable either returns the string index of the |
1231 // PushToStringTable either returns the string index of the |
| 1233 // string if it finds it in the table, or writes it to the |
1232 // string if it finds it in the table, or writes it to the |
| 1234 // table and returns it index if it doesn't find it there. |
1233 // table and returns it index if it doesn't find it there. |
| 1235 MustString (true); |
1234 m_lx->must_be (tk_string); |
| 1236 b->write_string (TOKEN); |
1235 b->write_string (TOKEN); |
| 1237 break; |
1236 break; |
| 1238 } |
1237 } |
| 1239 } |
1238 } |
| 1240 |
1239 |
| 1241 // Negate it now if desired |
1240 // Negate it now if desired |
| 1242 if (negate) |
1241 if (negate) |
| 1243 b->write (DH_NEGATELOGICAL); |
1242 b->write (dh_negate_logical); |
| 1244 |
1243 |
| 1245 return b; |
1244 return b; |
| 1246 } |
1245 } |
| 1247 |
1246 |
| 1248 // ============================================================================ |
1247 // ============================================================================ |
| 1258 int oper = parse_operator(); |
1257 int oper = parse_operator(); |
| 1259 |
1258 |
| 1260 if (!is_assignment_operator (oper)) |
1259 if (!is_assignment_operator (oper)) |
| 1261 error ("expected assignment operator"); |
1260 error ("expected assignment operator"); |
| 1262 |
1261 |
| 1263 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction |
1262 if (g_CurMode == MODE_TOPLEVEL) |
| 1264 error ("can't alter variables at top level"); |
1263 error ("can't alter variables at top level"); |
| 1265 |
1264 |
| 1266 // Parse the right operand |
1265 // Parse the right operand |
| 1267 m_lx->must_get_next(); |
1266 m_lx->must_get_next(); |
| 1268 data_buffer* retbuf = new data_buffer; |
1267 data_buffer* retbuf = new data_buffer; |
| 1271 // <<= and >>= do not have data headers. Solution: expand them. |
1270 // <<= and >>= do not have data headers. Solution: expand them. |
| 1272 // a <<= b -> a = a << b |
1271 // a <<= b -> a = a << b |
| 1273 // a >>= b -> a = a >> b |
1272 // a >>= b -> a = a >> b |
| 1274 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) |
1273 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) |
| 1275 { |
1274 { |
| 1276 retbuf->write (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR); |
1275 retbuf->write (global ? dh_push_global_var : dh_push_local_var); |
| 1277 retbuf->write (var->index); |
1276 retbuf->write (var->index); |
| 1278 retbuf->merge (expr); |
1277 retbuf->merge (expr); |
| 1279 retbuf->write ( (oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT); |
1278 retbuf->write ((oper == OPER_ASSIGNLEFTSHIFT) ? dh_left_shift : dh_right_shift); |
| 1280 retbuf->write (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR); |
1279 retbuf->write (global ? dh_assign_global_var : dh_assign_local_var); |
| 1281 retbuf->write (var->index); |
1280 retbuf->write (var->index); |
| 1282 } |
1281 } |
| 1283 else |
1282 else |
| 1284 { |
1283 { |
| 1285 retbuf->merge (expr); |
1284 retbuf->merge (expr); |
| 1348 // Init a buffer for the case block and tell the object |
1347 // Init a buffer for the case block and tell the object |
| 1349 // writer to record all written data to it. |
1348 // writer to record all written data to it. |
| 1350 info->casebuffers[info->casecursor] = w->SwitchBuffer = new data_buffer; |
1349 info->casebuffers[info->casecursor] = w->SwitchBuffer = new data_buffer; |
| 1351 } |
1350 } |
| 1352 |
1351 |
| 1353 constant_info* find_constant (string TOKEN) |
1352 constant_info* find_constant (string tok) |
| 1354 { |
1353 { |
| 1355 for (int i = 0; i < g_ConstInfo.size(); i++) |
1354 for (int i = 0; i < g_ConstInfo.size(); i++) |
| 1356 if (g_ConstInfo[i].name == TOKEN) |
1355 if (g_ConstInfo[i].name == tok) |
| 1357 return &g_ConstInfo[i]; |
1356 return &g_ConstInfo[i]; |
| 1358 |
1357 |
| 1359 return null; |
1358 return null; |
| 1360 } |
1359 } |
| 1361 |
1360 |