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 |