1
/* ------------------------------------------------------------------------- */
2
/* "states" : Statement translator */
4
/* Part of Inform 6.30 */
5
/* copyright (c) Graham Nelson 1993 - 2004 */
7
/* ------------------------------------------------------------------------- */
11
static int match_colon(void)
13
if (token_type == SEP_TT)
14
{ if (token_value == SEMICOLON_SEP)
15
warning("Unlike C, Inform uses ':' to divide parts \
16
of a 'for' loop specification: replacing ';' with ':'");
18
if (token_value != COLON_SEP)
19
{ ebf_error("':'", token_text);
20
panic_mode_error_recovery();
25
{ ebf_error("':'", token_text);
26
panic_mode_error_recovery();
32
static void match_open_bracket(void)
34
if ((token_type == SEP_TT) && (token_value == OPENB_SEP)) return;
36
ebf_error("'('", token_text);
39
extern void match_close_bracket(void)
41
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP)) return;
43
ebf_error("')'", token_text);
46
static void parse_action(void)
47
{ int level = 1, args = 0, codegen_action;
48
assembly_operand AO, AO2, AO3, AO4;
50
dont_enter_into_symbol_table = TRUE;
52
if ((token_type == SEP_TT) && (token_value == LESS_SEP))
53
{ level = 2; get_next_token();
55
dont_enter_into_symbol_table = FALSE;
57
if ((token_type==SEP_TT) && (token_value==OPENB_SEP))
59
AO2 = parse_expression(ACTION_Q_CONTEXT);
60
codegen_action = TRUE;
63
{ codegen_action = FALSE;
64
AO2 = action_of_name(token_text);
68
if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
71
AO3 = parse_expression(ACTION_Q_CONTEXT);
74
if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
77
AO4 = parse_expression(QUANTITY_CONTEXT);
83
if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
85
ebf_error("'>>'", token_text);
91
AO = veneer_routine(R_Process_VR);
95
if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
96
if (version_number>=5)
97
assemblez_2(call_2n_zc, AO, AO2);
99
if (version_number==4)
100
assemblez_2_to(call_vs_zc, AO, AO2, temp_var1);
102
assemblez_2_to(call_zc, AO, AO2, temp_var1);
105
AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
106
if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
107
if (version_number>=5)
108
assemblez_3(call_vn_zc, AO, AO2, AO3);
110
if (version_number==4)
111
assemblez_3_to(call_vs_zc, AO, AO2, AO3, temp_var1);
113
assemblez_3_to(call_zc, AO, AO2, AO3, temp_var1);
116
AO4 = code_generate(AO4, QUANTITY_CONTEXT, -1);
117
AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
118
if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
119
if (version_number>=5)
120
assemblez_4(call_vn_zc, AO, AO2, AO3, AO4);
122
if (version_number==4)
123
assemblez_4_to(call_vs_zc, AO, AO2, AO3, AO4, temp_var1);
125
assemblez_4(call_zc, AO, AO2, AO3, AO4);
129
if (level == 2) assemblez_0(rtrue_zc);
134
AO = veneer_routine(R_Process_VR);
140
AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
141
assembleg_call_1(AO, AO2, zero_operand);
145
AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
147
AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
148
assembleg_call_2(AO, AO2, AO3, zero_operand);
152
AO4 = code_generate(AO4, QUANTITY_CONTEXT, -1);
153
AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
155
AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
156
assembleg_call_3(AO, AO2, AO3, AO4, zero_operand);
161
assembleg_1(return_gc, one_operand);
166
extern int parse_label(void)
170
if ((token_type == SYMBOL_TT) &&
171
(stypes[token_value] == LABEL_T))
172
{ sflags[token_value] |= USED_SFLAG;
173
return(svals[token_value]);
176
if ((token_type == SYMBOL_TT) && (sflags[token_value] & UNKNOWN_SFLAG))
177
{ assign_symbol(token_value, next_label, LABEL_T);
178
define_symbol_label(token_value);
180
sflags[token_value] |= CHANGE_SFLAG + USED_SFLAG;
181
return(svals[token_value]);
184
ebf_error("label name", token_text);
188
static void parse_print_z(int finally_return)
189
{ int count = 0; assembly_operand AO;
191
/* print <printlist> -------------------------------------------------- */
192
/* print_ret <printlist> ---------------------------------------------- */
193
/* <literal-string> --------------------------------------------------- */
195
/* <printlist> is a comma-separated list of items: */
197
/* <literal-string> */
198
/* <other-expression> */
199
/* (char) <expression> */
200
/* (address) <expression> */
201
/* (string) <expression> */
202
/* (a) <expression> */
203
/* (the) <expression> */
204
/* (The) <expression> */
205
/* (name) <expression> */
206
/* (number) <expression> */
207
/* (property) <expression> */
208
/* (<routine>) <expression> */
209
/* (object) <expression> (for use in low-level code only) */
210
/* --------------------------------------------------------------------- */
213
{ AI.text = token_text;
214
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
217
if (strlen(token_text) > 32)
218
{ AO.marker = STRING_MV;
219
AO.type = LONG_CONSTANT_OT;
220
AO.value = compile_string(token_text, FALSE, FALSE);
221
assemblez_1(print_paddr_zc, AO);
224
if ((token_type == SEP_TT)
225
&& (token_value == SEMICOLON_SEP))
226
{ assemblez_0(new_line_zc);
227
assemblez_0(rtrue_zc);
236
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
237
{ assemblez_0(print_ret_zc); return;
241
assemblez_0(print_zc);
245
if (token_value == OPENB_SEP)
246
{ misc_keywords.enabled = TRUE;
249
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
250
{ assembly_operand AO1;
252
put_token_back(); put_token_back();
253
local_variables.enabled = FALSE;
255
misc_keywords.enabled = FALSE;
256
local_variables.enabled = TRUE;
258
if ((token_type == STATEMENT_TT)
259
&&(token_value == STRING_CODE))
260
{ token_type = MISC_KEYWORD_TT;
261
token_value = STRING_MK;
266
case MISC_KEYWORD_TT:
269
if (runtime_error_checking_switch)
270
{ AO = veneer_routine(RT__ChPrintC_VR);
275
parse_expression(QUANTITY_CONTEXT),
276
QUANTITY_CONTEXT, -1);
277
assemblez_1(print_char_zc, AO1);
280
if (runtime_error_checking_switch)
281
{ AO = veneer_routine(RT__ChPrintA_VR);
286
parse_expression(QUANTITY_CONTEXT),
287
QUANTITY_CONTEXT, -1);
288
assemblez_1(print_addr_zc, AO1);
291
if (runtime_error_checking_switch)
292
{ AO = veneer_routine(RT__ChPrintS_VR);
297
parse_expression(QUANTITY_CONTEXT),
298
QUANTITY_CONTEXT, -1);
299
assemblez_1(print_paddr_zc, AO1);
302
if (runtime_error_checking_switch)
303
{ AO = veneer_routine(RT__ChPrintO_VR);
308
parse_expression(QUANTITY_CONTEXT),
309
QUANTITY_CONTEXT, -1);
310
assemblez_1(print_obj_zc, AO1);
313
AO = veneer_routine(DefArt_VR);
317
AO = veneer_routine(InDefArt_VR);
320
AO = veneer_routine(CDefArt_VR);
323
AO = veneer_routine(CInDefArt_VR);
326
AO = veneer_routine(PrintShortName_VR);
329
AO = veneer_routine(EnglishNumber_VR);
332
AO = veneer_routine(Print__Pname_VR);
335
error_named("A reserved word was used as a print specification:",
341
if (sflags[token_value] & UNKNOWN_SFLAG)
342
{ AO.type = LONG_CONSTANT_OT;
343
AO.value = token_value;
344
AO.marker = SYMBOL_MV;
347
{ AO.type = LONG_CONSTANT_OT;
348
AO.value = svals[token_value];
349
AO.marker = IROUTINE_MV;
350
if (stypes[token_value] != ROUTINE_T)
351
ebf_error("printing routine name", token_text);
353
sflags[token_value] |= USED_SFLAG;
358
if (version_number >= 5)
359
assemblez_2(call_2n_zc, AO,
360
code_generate(parse_expression(QUANTITY_CONTEXT),
361
QUANTITY_CONTEXT, -1));
362
else if (version_number == 4)
363
assemblez_2_to(call_vs_zc, AO,
364
code_generate(parse_expression(QUANTITY_CONTEXT),
365
QUANTITY_CONTEXT, -1), temp_var1);
367
assemblez_2_to(call_zc, AO,
368
code_generate(parse_expression(QUANTITY_CONTEXT),
369
QUANTITY_CONTEXT, -1), temp_var1);
372
default: ebf_error("print specification", token_text);
374
assemblez_1(print_num_zc,
375
code_generate(parse_expression(QUANTITY_CONTEXT),
376
QUANTITY_CONTEXT, -1));
380
put_token_back(); put_token_back(); put_token_back();
381
misc_keywords.enabled = FALSE;
382
assemblez_1(print_num_zc,
383
code_generate(parse_expression(QUANTITY_CONTEXT),
384
QUANTITY_CONTEXT, -1));
389
put_token_back(); misc_keywords.enabled = FALSE;
390
assemblez_1(print_num_zc,
391
code_generate(parse_expression(QUANTITY_CONTEXT),
392
QUANTITY_CONTEXT, -1));
396
PrintTermDone: misc_keywords.enabled = FALSE;
400
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
401
if ((token_type != SEP_TT) || (token_value != COMMA_SEP))
402
{ ebf_error("comma", token_text);
403
panic_mode_error_recovery(); return;
405
else get_next_token();
408
if (count == 0) ebf_error("something to print", token_text);
410
{ assemblez_0(new_line_zc);
411
assemblez_0(rtrue_zc);
415
static void parse_print_g(int finally_return)
416
{ int count = 0; assembly_operand AO, AO2;
418
/* print <printlist> -------------------------------------------------- */
419
/* print_ret <printlist> ---------------------------------------------- */
420
/* <literal-string> --------------------------------------------------- */
422
/* <printlist> is a comma-separated list of items: */
424
/* <literal-string> */
425
/* <other-expression> */
426
/* (char) <expression> */
427
/* (address) <expression> */
428
/* (string) <expression> */
429
/* (a) <expression> */
430
/* (A) <expression> */
431
/* (the) <expression> */
432
/* (The) <expression> */
433
/* (name) <expression> */
434
/* (number) <expression> */
435
/* (property) <expression> */
436
/* (<routine>) <expression> */
437
/* (object) <expression> (for use in low-level code only) */
438
/* --------------------------------------------------------------------- */
442
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
445
/* We can't compile a string into the instruction,
446
so this always goes into the string area. */
447
{ AO.marker = STRING_MV;
448
AO.type = CONSTANT_OT;
449
AO.value = compile_string(token_text, FALSE, FALSE);
450
assembleg_1(streamstr_gc, AO);
453
if ((token_type == SEP_TT)
454
&& (token_value == SEMICOLON_SEP))
455
{ AO.type = BYTECONSTANT_OT;
456
AO.value = 0x0A; AO.marker = 0;
457
assembleg_1(streamchar_gc, AO);
458
AO.type = BYTECONSTANT_OT;
459
AO.value = 1; AO.marker = 0;
460
assembleg_1(return_gc, AO);
470
if (token_value == OPENB_SEP)
471
{ misc_keywords.enabled = TRUE;
474
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
475
{ assembly_operand AO1;
477
put_token_back(); put_token_back();
478
local_variables.enabled = FALSE;
480
misc_keywords.enabled = FALSE;
481
local_variables.enabled = TRUE;
483
if ((token_type == STATEMENT_TT)
484
&&(token_value == STRING_CODE))
485
{ token_type = MISC_KEYWORD_TT;
486
token_value = STRING_MK;
491
case MISC_KEYWORD_TT:
494
if (runtime_error_checking_switch)
495
{ AO = veneer_routine(RT__ChPrintC_VR);
500
parse_expression(QUANTITY_CONTEXT),
501
QUANTITY_CONTEXT, -1);
502
assembleg_1(streamchar_gc, AO1);
505
if (runtime_error_checking_switch)
506
AO = veneer_routine(RT__ChPrintA_VR);
508
AO = veneer_routine(Print__Addr_VR);
511
if (runtime_error_checking_switch)
512
{ AO = veneer_routine(RT__ChPrintS_VR);
517
parse_expression(QUANTITY_CONTEXT),
518
QUANTITY_CONTEXT, -1);
519
assembleg_1(streamstr_gc, AO1);
522
if (runtime_error_checking_switch)
523
{ AO = veneer_routine(RT__ChPrintO_VR);
528
parse_expression(QUANTITY_CONTEXT),
529
QUANTITY_CONTEXT, -1);
530
AO2.type = BYTECONSTANT_OT;
533
assembleg_3(aload_gc, AO1, AO2,
535
assembleg_1(streamstr_gc, stack_pointer);
538
AO = veneer_routine(DefArt_VR);
542
AO = veneer_routine(InDefArt_VR);
545
AO = veneer_routine(CDefArt_VR);
548
AO = veneer_routine(CInDefArt_VR);
551
AO = veneer_routine(PrintShortName_VR);
554
AO = veneer_routine(EnglishNumber_VR);
557
AO = veneer_routine(Print__Pname_VR);
560
error_named("A reserved word was used as a print specification:",
566
if (sflags[token_value] & UNKNOWN_SFLAG)
567
{ AO.type = CONSTANT_OT;
568
AO.value = token_value;
569
AO.marker = SYMBOL_MV;
572
{ AO.type = CONSTANT_OT;
573
AO.value = svals[token_value];
574
AO.marker = IROUTINE_MV;
575
if (stypes[token_value] != ROUTINE_T)
576
ebf_error("printing routine name", token_text);
578
sflags[token_value] |= USED_SFLAG;
583
AO2.type = ZEROCONSTANT_OT;
584
AO2.value = 0; AO2.marker = 0;
586
code_generate(parse_expression(QUANTITY_CONTEXT),
587
QUANTITY_CONTEXT, -1),
591
default: ebf_error("print specification", token_text);
593
assembleg_1(streamnum_gc,
594
code_generate(parse_expression(QUANTITY_CONTEXT),
595
QUANTITY_CONTEXT, -1));
599
put_token_back(); put_token_back(); put_token_back();
600
misc_keywords.enabled = FALSE;
601
assembleg_1(streamnum_gc,
602
code_generate(parse_expression(QUANTITY_CONTEXT),
603
QUANTITY_CONTEXT, -1));
608
put_token_back(); misc_keywords.enabled = FALSE;
609
assembleg_1(streamnum_gc,
610
code_generate(parse_expression(QUANTITY_CONTEXT),
611
QUANTITY_CONTEXT, -1));
615
PrintTermDone: misc_keywords.enabled = FALSE;
619
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
620
if ((token_type != SEP_TT) || (token_value != COMMA_SEP))
621
{ ebf_error("comma", token_text);
622
panic_mode_error_recovery(); return;
624
else get_next_token();
627
if (count == 0) ebf_error("something to print", token_text);
630
AO.type = BYTECONSTANT_OT; AO.value = 0x0A; AO.marker = 0;
631
assembleg_1(streamchar_gc, AO);
632
AO.type = BYTECONSTANT_OT; AO.value = 1; AO.marker = 0;
633
assembleg_1(return_gc, AO);
637
static void parse_statement_z(int break_label, int continue_label)
638
{ int ln, ln2, ln3, ln4, flag;
639
assembly_operand AO, AO2, AO3, AO4;
640
dbgl spare_dbgl1, spare_dbgl2;
644
if ((token_type == SEP_TT) && (token_value == PROPERTY_SEP))
645
{ /* That is, a full stop, signifying a label */
648
if (token_type == SYMBOL_TT)
650
if (sflags[token_value] & UNKNOWN_SFLAG)
651
{ assign_symbol(token_value, next_label, LABEL_T);
652
sflags[token_value] |= USED_SFLAG;
653
assemble_label_no(next_label);
654
define_symbol_label(token_value);
658
{ if (stypes[token_value] != LABEL_T) goto LabelError;
659
if (sflags[token_value] & CHANGE_SFLAG)
660
{ sflags[token_value] &= (~(CHANGE_SFLAG));
661
assemble_label_no(svals[token_value]);
662
define_symbol_label(token_value);
664
else error_named("Duplicate definition of label:", token_text);
668
if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
669
{ ebf_error("';'", token_text);
670
put_token_back(); return;
673
/* Interesting point of Inform grammar: a statement can only
674
consist solely of a label when it is immediately followed
678
if ((token_type == SEP_TT) && (token_value == CLOSE_BRACE_SEP))
679
{ put_token_back(); return;
681
parse_statement(break_label, continue_label);
684
LabelError: ebf_error("label name", token_text);
687
if ((token_type == SEP_TT) && (token_value == HASH_SEP))
688
{ parse_directive(TRUE);
689
parse_statement(break_label, continue_label); return;
692
if ((token_type == SEP_TT) && (token_value == AT_SEP))
693
{ parse_assembly(); return;
696
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return;
698
if (token_type == DQ_TT)
699
{ parse_print_z(TRUE); return;
702
if ((token_type == SEP_TT) && (token_value == LESS_SEP))
703
{ parse_action(); goto StatementTerminator; }
705
if (token_type == EOF_TT)
706
{ ebf_error("statement", token_text); return; }
708
if (token_type != STATEMENT_TT)
710
AO = parse_expression(VOID_CONTEXT);
711
code_generate(AO, VOID_CONTEXT, -1);
712
if (vivc_flag) { panic_mode_error_recovery(); return; }
713
goto StatementTerminator;
716
statements.enabled = FALSE;
720
/* -------------------------------------------------------------------- */
721
/* box <string-1> ... <string-n> -------------------------------------- */
722
/* -------------------------------------------------------------------- */
725
if (version_number == 3)
726
warning("The 'box' statement has no effect in a version 3 game");
727
AO3.type = LONG_CONSTANT_OT;
728
AO3.value = begin_table_array();
729
AO3.marker = ARRAY_MV;
733
if ((token_type==SEP_TT)&&(token_value==SEMICOLON_SEP))
735
if (token_type != DQ_TT)
736
ebf_error("text of box line in double-quotes",
739
for (i=0, j=0; token_text[i] != 0; j++)
740
if (token_text[i] == '@')
741
{ if (token_text[i+1] == '@')
743
while (isdigit(token_text[i])) i++;
747
if (token_text[i] != 0) i++;
748
if (token_text[i] != 0) i++;
752
if (j > ln2) ln2 = j;
755
array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
759
error("No lines of text given for 'box' display");
761
if (version_number == 3) return;
763
AO2.type = SHORT_CONSTANT_OT; AO2.value = ln2; AO2.marker = 0;
764
AO4.type = VARIABLE_OT; AO4.value = 255; AO4.marker = 0;
765
assemblez_3_to(call_vs_zc, veneer_routine(Box__Routine_VR),
769
/* -------------------------------------------------------------------- */
770
/* break -------------------------------------------------------------- */
771
/* -------------------------------------------------------------------- */
774
if (break_label == -1)
775
error("'break' can only be used in a loop or 'switch' block");
777
assemblez_jump(break_label);
780
/* -------------------------------------------------------------------- */
781
/* continue ----------------------------------------------------------- */
782
/* -------------------------------------------------------------------- */
785
if (continue_label == -1)
786
error("'continue' can only be used in a loop block");
788
assemblez_jump(continue_label);
791
/* -------------------------------------------------------------------- */
792
/* do <codeblock> until (<condition>) --------------------------------- */
793
/* -------------------------------------------------------------------- */
796
assemble_label_no(ln = next_label++);
797
ln2 = next_label++; ln3 = next_label++;
798
parse_code_block(ln3, ln2, 0);
799
statements.enabled = TRUE;
801
if ((token_type == STATEMENT_TT)
802
&& (token_value == UNTIL_CODE))
803
{ assemble_label_no(ln2);
804
match_open_bracket();
805
AO = parse_expression(CONDITION_CONTEXT);
806
match_close_bracket();
807
code_generate(AO, CONDITION_CONTEXT, ln);
809
else error("'do' without matching 'until'");
811
assemble_label_no(ln3);
814
/* -------------------------------------------------------------------- */
815
/* font on/off -------------------------------------------------------- */
816
/* -------------------------------------------------------------------- */
819
misc_keywords.enabled = TRUE;
821
misc_keywords.enabled = FALSE;
822
if ((token_type != MISC_KEYWORD_TT)
823
|| ((token_value != ON_MK)
824
&& (token_value != OFF_MK)))
825
{ ebf_error("'on' or 'off'", token_text);
826
panic_mode_error_recovery();
830
AO.type = SHORT_CONSTANT_OT;
833
AO2.type = SHORT_CONSTANT_OT;
836
AO3.type = VARIABLE_OT;
839
assemblez_2_to(loadw_zc, AO, AO2, AO3);
841
if (token_value == ON_MK)
842
{ AO4.type = LONG_CONSTANT_OT;
845
assemblez_2_to(and_zc, AO4, AO3, AO3);
848
{ AO4.type = SHORT_CONSTANT_OT;
851
assemblez_2_to(or_zc, AO4, AO3, AO3);
854
assemblez_3(storew_zc, AO, AO2, AO3);
857
/* -------------------------------------------------------------------- */
858
/* for (<initialisation> : <continue-condition> : <updating>) --------- */
859
/* -------------------------------------------------------------------- */
861
/* Note that it's legal for any or all of the three sections of a
862
'for' specification to be empty. This 'for' implementation
863
often wastes 3 bytes with a redundant branch rather than keep
864
expression parse trees for long periods (as previous versions
865
of Inform did, somewhat crudely by simply storing the textual
866
form of a 'for' loop). It is adequate for now. */
869
match_open_bracket();
872
/* Initialisation code */
874
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
876
if (!((token_type==SEP_TT)&&(token_value==SUPERCLASS_SEP)))
877
{ sequence_point_follows = TRUE;
878
debug_line_ref = token_line_ref;
879
code_generate(parse_expression(FORINIT_CONTEXT),
883
if ((token_type==SEP_TT)&&(token_value == SUPERCLASS_SEP))
885
if ((token_type==SEP_TT)&&(token_value == CLOSEB_SEP))
886
{ assemble_label_no(ln = next_label++);
888
parse_code_block(ln2, ln, 0);
889
sequence_point_follows = FALSE;
890
if (!execution_never_reaches_here)
892
assemble_label_no(ln2);
895
AO.type = OMITTED_OT;
899
if (!match_colon()) break;
903
AO.type = OMITTED_OT;
904
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
906
spare_dbgl1 = token_line_ref;
907
AO = parse_expression(CONDITION_CONTEXT);
908
if (!match_colon()) break;
913
AO2.type = OMITTED_OT; flag = 0;
914
if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
916
spare_dbgl2 = token_line_ref;
917
AO2 = parse_expression(VOID_CONTEXT);
918
match_close_bracket();
919
flag = test_for_incdec(AO2);
926
if ((AO2.type == OMITTED_OT) || (flag != 0))
928
assemble_label_no(ln);
929
if (flag==0) assemble_label_no(ln2);
931
/* The "finished yet?" condition */
933
if (AO.type != OMITTED_OT)
934
{ sequence_point_follows = TRUE;
935
debug_line_ref = spare_dbgl1;
936
code_generate(AO, CONDITION_CONTEXT, ln3);
942
/* This is the jump which could be avoided with the aid
943
of long-term expression storage */
945
sequence_point_follows = FALSE;
948
/* The "update" part */
950
assemble_label_no(ln);
951
sequence_point_follows = TRUE;
952
debug_line_ref = spare_dbgl2;
953
code_generate(AO2, VOID_CONTEXT, -1);
955
assemble_label_no(ln2);
957
/* The "finished yet?" condition */
959
if (AO.type != OMITTED_OT)
960
{ sequence_point_follows = TRUE;
961
debug_line_ref = spare_dbgl1;
962
code_generate(AO, CONDITION_CONTEXT, ln3);
968
/* In this optimised case, update code is at the end
969
of the loop block, so "continue" goes there */
971
parse_code_block(ln3, ln2, 0);
972
assemble_label_no(ln2);
974
sequence_point_follows = TRUE;
975
debug_line_ref = spare_dbgl2;
977
{ AO3.type = SHORT_CONSTANT_OT;
980
&& (flag>=MAX_LOCAL_VARIABLES) && (flag<LOWEST_SYSTEM_VAR_NUMBER))
981
AO3.marker = VARIABLE_MV;
983
assemblez_1(inc_zc, AO3);
986
{ AO3.type = SHORT_CONSTANT_OT;
988
if ((module_switch) && (flag>=MAX_LOCAL_VARIABLES)
989
&& (flag<LOWEST_SYSTEM_VAR_NUMBER))
990
AO3.marker = VARIABLE_MV;
992
assemblez_1(dec_zc, AO3);
998
/* In the unoptimised case, update code is at the
999
start of the loop block, so "continue" goes there */
1001
parse_code_block(ln3, ln, 0);
1002
if (!execution_never_reaches_here)
1003
{ sequence_point_follows = FALSE;
1008
assemble_label_no(ln3);
1011
/* -------------------------------------------------------------------- */
1012
/* give <expression> [~]attr [, [~]attr [, ...]] ---------------------- */
1013
/* -------------------------------------------------------------------- */
1016
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1017
QUANTITY_CONTEXT, -1);
1018
if ((AO.type == VARIABLE_OT) && (AO.value == 0))
1021
AO.type = SHORT_CONSTANT_OT;
1022
if (version_number != 6) assemblez_1(pull_zc, AO);
1023
else assemblez_0_to(pull_zc, AO);
1024
AO.type = VARIABLE_OT;
1029
if ((token_type == SEP_TT)&&(token_value == SEMICOLON_SEP))
1031
if ((token_type == SEP_TT)&&(token_value == ARTNOT_SEP))
1034
{ if ((token_type == SYMBOL_TT)
1035
&& (stypes[token_value] != ATTRIBUTE_T))
1036
warning_named("This is not a declared Attribute:",
1041
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1042
QUANTITY_CONTEXT, -1);
1043
if (runtime_error_checking_switch)
1044
{ /* ln2 = next_label++;
1045
check_nonzero_at_runtime(AO, ln2, GIVE_RTE);
1046
assemblez_2(ln, AO, AO2);
1047
assemble_label_no(ln2); */
1048
ln2 = (ln==set_attr_zc)?RT__ChG_VR:RT__ChGt_VR;
1049
if (version_number >= 5)
1050
assemblez_3(call_vn_zc, veneer_routine(ln2),
1054
assemblez_3_to(call_zc, veneer_routine(ln2),
1055
AO, AO2, temp_var1);
1059
assemblez_2(ln, AO, AO2);
1062
/* -------------------------------------------------------------------- */
1063
/* if (<condition>) <codeblock> [else <codeblock>] -------------------- */
1064
/* -------------------------------------------------------------------- */
1069
match_open_bracket();
1070
AO = parse_expression(CONDITION_CONTEXT);
1071
match_close_bracket();
1073
statements.enabled = TRUE;
1075
if ((token_type == STATEMENT_TT)&&(token_value == RTRUE_CODE))
1078
if ((token_type == STATEMENT_TT)&&(token_value == RFALSE_CODE))
1085
code_generate(AO, CONDITION_CONTEXT, ln);
1087
if (ln >= 0) parse_code_block(break_label, continue_label, 0);
1090
if ((token_type != SEP_TT)
1091
|| (token_value != SEMICOLON_SEP))
1092
{ ebf_error("';'", token_text);
1097
statements.enabled = TRUE;
1099
if ((token_type == STATEMENT_TT) && (token_value == ELSE_CODE))
1102
{ ln2 = next_label++;
1103
if (!execution_never_reaches_here)
1104
{ sequence_point_follows = FALSE;
1105
assemblez_jump(ln2);
1109
else put_token_back();
1111
if (ln >= 0) assemble_label_no(ln);
1114
{ parse_code_block(break_label, continue_label, 0);
1115
if (ln >= 0) assemble_label_no(ln2);
1120
/* -------------------------------------------------------------------- */
1121
/* inversion ---------------------------------------------------------- */
1122
/* -------------------------------------------------------------------- */
1124
case INVERSION_CODE:
1126
AO.type = SHORT_CONSTANT_OT;
1130
AO2.type = SHORT_CONSTANT_OT;
1133
assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1134
assemblez_1(print_char_zc, temp_var1);
1136
assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1137
assemblez_1(print_char_zc, temp_var1);
1139
assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1140
assemblez_1(print_char_zc, temp_var1);
1142
assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1143
assemblez_1(print_char_zc, temp_var1);
1146
/* -------------------------------------------------------------------- */
1147
/* jump <label> ------------------------------------------------------- */
1148
/* -------------------------------------------------------------------- */
1151
assemblez_jump(parse_label());
1154
/* -------------------------------------------------------------------- */
1155
/* move <expression> to <expression> ---------------------------------- */
1156
/* -------------------------------------------------------------------- */
1159
misc_keywords.enabled = TRUE;
1160
AO = parse_expression(QUANTITY_CONTEXT);
1163
misc_keywords.enabled = FALSE;
1164
if ((token_type != MISC_KEYWORD_TT)
1165
|| (token_value != TO_MK))
1166
{ ebf_error("'to'", token_text);
1167
panic_mode_error_recovery();
1171
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1172
QUANTITY_CONTEXT, -1);
1173
AO = code_generate(AO, QUANTITY_CONTEXT, -1);
1174
if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
1175
{ if (version_number >= 5)
1176
assemblez_3(call_vn_zc, veneer_routine(RT__ChT_VR),
1179
{ assemblez_3_to(call_zc, veneer_routine(RT__ChT_VR),
1180
AO, AO2, temp_var1);
1184
assemblez_2(insert_obj_zc, AO, AO2);
1187
/* -------------------------------------------------------------------- */
1188
/* new_line ----------------------------------------------------------- */
1189
/* -------------------------------------------------------------------- */
1191
case NEW_LINE_CODE: assemblez_0(new_line_zc); break;
1193
/* -------------------------------------------------------------------- */
1194
/* objectloop (<initialisation>) <codeblock> -------------------------- */
1195
/* -------------------------------------------------------------------- */
1197
case OBJECTLOOP_CODE:
1199
match_open_bracket();
1201
if (token_type == LOCAL_VARIABLE_TT)
1202
AO.value = token_value;
1204
if ((token_type == SYMBOL_TT) &&
1205
(stypes[token_value] == GLOBAL_VARIABLE_T))
1206
AO.value = svals[token_value];
1208
{ ebf_error("'objectloop' variable", token_text);
1209
panic_mode_error_recovery(); break;
1211
AO.type = VARIABLE_OT;
1212
if ((module_switch) && (AO.value >= MAX_LOCAL_VARIABLES)
1213
&& (AO.value < LOWEST_SYSTEM_VAR_NUMBER))
1214
AO.marker = VARIABLE_MV;
1216
misc_keywords.enabled = TRUE;
1217
get_next_token(); flag = TRUE;
1218
misc_keywords.enabled = FALSE;
1219
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
1223
if ((token_type == MISC_KEYWORD_TT)
1224
&& (token_value == NEAR_MK)) ln = 1;
1225
if ((token_type == MISC_KEYWORD_TT)
1226
&& (token_value == FROM_MK)) ln = 2;
1227
if ((token_type == CND_TT) && (token_value == IN_COND))
1230
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
1237
{ /* Old style (Inform 5) objectloops: note that we
1238
implement objectloop (a in b) in the old way since
1239
this runs through objects in a different order from
1240
the new way, and there may be existing Inform code
1242
assembly_operand AO4;
1244
sequence_point_follows = TRUE;
1245
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1246
QUANTITY_CONTEXT, -1);
1247
match_close_bracket();
1249
{ AO3.type = VARIABLE_OT; AO3.value = 0; AO3.marker = 0;
1250
if (runtime_error_checking_switch)
1251
AO2 = check_nonzero_at_runtime(AO2, -1,
1253
assemblez_1_to(get_parent_zc, AO2, AO3);
1254
assemblez_objcode(get_child_zc, AO3, AO3, -2, TRUE);
1258
{ AO3.type = VARIABLE_OT; AO3.value = 0; AO3.marker = 0;
1259
if (runtime_error_checking_switch)
1261
AO2 = check_nonzero_at_runtime(AO2, -1,
1264
assemblez_objcode(get_child_zc, AO2, AO3, -2, TRUE);
1267
assemblez_store(AO, AO2);
1268
assemblez_1_branch(jz_zc, AO, ln2 = next_label++, TRUE);
1269
assemble_label_no(ln4 = next_label++);
1270
parse_code_block(ln2, ln3 = next_label++, 0);
1271
sequence_point_follows = FALSE;
1272
assemble_label_no(ln3);
1273
if (runtime_error_checking_switch)
1274
{ AO2 = check_nonzero_at_runtime(AO, ln2,
1277
&& ((AO4.type != VARIABLE_OT)||(AO4.value != 0))
1278
&& ((AO4.type != VARIABLE_OT)
1279
||(AO4.value != AO.value)))
1280
{ assembly_operand en_ao;
1281
en_ao.value = OBJECTLOOP_BROKEN_RTE;
1283
en_ao.type = SHORT_CONSTANT_OT;
1284
assemblez_2_branch(jin_zc, AO, AO4,
1286
assemblez_3(call_vn_zc, veneer_routine(RT__Err_VR),
1288
assemblez_jump(ln2);
1289
assemble_label_no(next_label++);
1293
assemblez_objcode(get_sibling_zc, AO2, AO, ln4, TRUE);
1294
assemble_label_no(ln2);
1298
sequence_point_follows = TRUE;
1299
AO2.type = SHORT_CONSTANT_OT; AO2.value = 1; AO2.marker = 0;
1300
assemblez_store(AO, AO2);
1302
assemble_label_no(ln = next_label++);
1308
sequence_point_follows = TRUE;
1309
code_generate(parse_expression(CONDITION_CONTEXT),
1310
CONDITION_CONTEXT, ln3);
1311
match_close_bracket();
1313
parse_code_block(ln2, ln3, 0);
1315
sequence_point_follows = FALSE;
1316
assemble_label_no(ln3);
1318
AO2.type = LONG_CONSTANT_OT; AO2.value = no_objects;
1319
AO2.marker = NO_OBJS_MV;
1320
assemblez_2_branch(jg_zc, AO, AO2, ln2, TRUE);
1322
assemble_label_no(ln2);
1325
/* -------------------------------------------------------------------- */
1326
/* (see routine above) ------------------------------------------------ */
1327
/* -------------------------------------------------------------------- */
1331
parse_print_z(FALSE); return;
1332
case PRINT_RET_CODE:
1334
parse_print_z(TRUE); return;
1336
/* -------------------------------------------------------------------- */
1337
/* quit --------------------------------------------------------------- */
1338
/* -------------------------------------------------------------------- */
1340
case QUIT_CODE: assemblez_0(quit_zc); break;
1342
/* -------------------------------------------------------------------- */
1343
/* read <expression> <expression> [<Routine>] ------------------------- */
1344
/* -------------------------------------------------------------------- */
1347
AO.type = VARIABLE_OT; AO.value = 252; AO.marker = 0;
1349
code_generate(parse_expression(QUANTITY_CONTEXT),
1350
QUANTITY_CONTEXT, -1));
1351
if (version_number > 3)
1352
{ AO3.type = SHORT_CONSTANT_OT; AO3.value = 1;AO3.marker = 0;
1353
AO4.type = SHORT_CONSTANT_OT; AO4.value = 0;AO4.marker = 0;
1354
assemblez_3(storeb_zc, AO, AO3, AO4);
1356
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1357
QUANTITY_CONTEXT, -1);
1360
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
1363
{ if (version_number == 3)
1365
"In Version 3 no status-line drawing routine can be given");
1367
{ assembly_operand AO5;
1369
AO5 = parse_expression(CONSTANT_CONTEXT);
1371
if (version_number >= 5)
1372
assemblez_1(call_1n_zc, AO5);
1374
assemblez_1_to(call_zc, AO5, temp_var1);
1378
if (version_number > 4)
1379
{ assemblez_2_to(aread_zc, AO, AO2, temp_var1);
1381
else assemblez_2(sread_zc, AO, AO2);
1384
/* -------------------------------------------------------------------- */
1385
/* remove <expression> ------------------------------------------------ */
1386
/* -------------------------------------------------------------------- */
1389
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1390
QUANTITY_CONTEXT, -1);
1391
if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
1392
{ if (version_number >= 5)
1393
assemblez_2(call_2n_zc, veneer_routine(RT__ChR_VR),
1396
{ assemblez_2_to(call_zc, veneer_routine(RT__ChR_VR),
1401
assemblez_1(remove_obj_zc, AO);
1404
/* -------------------------------------------------------------------- */
1405
/* restore <label> ---------------------------------------------------- */
1406
/* -------------------------------------------------------------------- */
1409
if (version_number < 5)
1410
assemblez_0_branch(restore_zc, parse_label(), TRUE);
1412
{ AO2.type = SHORT_CONSTANT_OT; AO2.value = 2;
1414
assemblez_0_to(restore_zc, temp_var1);
1415
assemblez_2_branch(je_zc, temp_var1, AO2, parse_label(), TRUE);
1419
/* -------------------------------------------------------------------- */
1420
/* return [<expression>] ---------------------------------------------- */
1421
/* -------------------------------------------------------------------- */
1425
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
1426
{ assemblez_0(rtrue_zc); return; }
1428
AO = code_generate(parse_expression(RETURN_Q_CONTEXT),
1429
QUANTITY_CONTEXT, -1);
1430
if ((AO.type == SHORT_CONSTANT_OT) && (AO.value == 0)
1431
&& (AO.marker == 0))
1432
{ assemblez_0(rfalse_zc); break; }
1433
if ((AO.type == SHORT_CONSTANT_OT) && (AO.value == 1)
1434
&& (AO.marker == 0))
1435
{ assemblez_0(rtrue_zc); break; }
1436
if ((AO.type == VARIABLE_OT) && (AO.value == 0))
1437
{ assemblez_0(ret_popped_zc); break; }
1438
assemblez_1(ret_zc, AO);
1441
/* -------------------------------------------------------------------- */
1442
/* rfalse ------------------------------------------------------------- */
1443
/* -------------------------------------------------------------------- */
1445
case RFALSE_CODE: assemblez_0(rfalse_zc); break;
1447
/* -------------------------------------------------------------------- */
1448
/* rtrue -------------------------------------------------------------- */
1449
/* -------------------------------------------------------------------- */
1451
case RTRUE_CODE: assemblez_0(rtrue_zc); break;
1453
/* -------------------------------------------------------------------- */
1454
/* save <label> ------------------------------------------------------- */
1455
/* -------------------------------------------------------------------- */
1458
if (version_number < 5)
1459
assemblez_0_branch(save_zc, parse_label(), TRUE);
1461
{ AO.type = VARIABLE_OT; AO.value = 255; AO.marker = 0;
1462
assemblez_0_to(save_zc, AO);
1463
assemblez_1_branch(jz_zc, AO, parse_label(), FALSE);
1467
/* -------------------------------------------------------------------- */
1468
/* spaces <expression> ------------------------------------------------ */
1469
/* -------------------------------------------------------------------- */
1472
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1473
QUANTITY_CONTEXT, -1);
1474
AO2.type = VARIABLE_OT; AO2.value = 255; AO2.marker = 0;
1476
assemblez_store(AO2, AO);
1478
AO.type = SHORT_CONSTANT_OT; AO.value = 32; AO.marker = 0;
1479
AO3.type = SHORT_CONSTANT_OT; AO3.value = 1; AO3.marker = 0;
1481
assemblez_2_branch(jl_zc, AO2, AO3, ln = next_label++, TRUE);
1482
assemble_label_no(ln2 = next_label++);
1483
assemblez_1(print_char_zc, AO);
1485
assemblez_1_branch(jz_zc, AO2, ln2, FALSE);
1486
assemble_label_no(ln);
1489
/* -------------------------------------------------------------------- */
1490
/* string <expression> <literal-string> ------------------------------- */
1491
/* -------------------------------------------------------------------- */
1494
AO.type = SHORT_CONSTANT_OT; AO.value = 0; AO.marker = 0;
1495
AO2.type = SHORT_CONSTANT_OT; AO2.value = 12; AO2.marker = 0;
1496
AO3.type = VARIABLE_OT; AO3.value = 252; AO3.marker = 0;
1497
assemblez_2_to(loadw_zc, AO, AO2, AO3);
1498
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1499
QUANTITY_CONTEXT, -1);
1501
if (token_type == DQ_TT)
1502
{ AO4.value = compile_string(token_text, TRUE, TRUE);
1504
AO4.type = LONG_CONSTANT_OT;
1508
AO4 = parse_expression(CONSTANT_CONTEXT);
1510
assemblez_3(storew_zc, AO3, AO2, AO4);
1513
/* -------------------------------------------------------------------- */
1514
/* style roman/reverse/bold/underline/fixed --------------------------- */
1515
/* -------------------------------------------------------------------- */
1518
if (version_number==3)
1520
"The 'style' statement cannot be used for Version 3 games");
1521
panic_mode_error_recovery();
1525
misc_keywords.enabled = TRUE;
1527
misc_keywords.enabled = FALSE;
1528
if ((token_type != MISC_KEYWORD_TT)
1529
|| ((token_value != ROMAN_MK)
1530
&& (token_value != REVERSE_MK)
1531
&& (token_value != BOLD_MK)
1532
&& (token_value != UNDERLINE_MK)
1533
&& (token_value != FIXED_MK)))
1535
"'roman', 'bold', 'underline', 'reverse' or 'fixed'",
1537
panic_mode_error_recovery();
1541
AO.type = SHORT_CONSTANT_OT; AO.marker = 0;
1543
{ case ROMAN_MK: AO.value = 0; break;
1544
case REVERSE_MK: AO.value = 1; break;
1545
case BOLD_MK: AO.value = 2; break;
1546
case UNDERLINE_MK: AO.value = 4; break;
1547
case FIXED_MK: AO.value = 8; break;
1549
assemblez_1(set_text_style_zc, AO); break;
1551
/* -------------------------------------------------------------------- */
1552
/* switch (<expression>) <codeblock> ---------------------------------- */
1553
/* -------------------------------------------------------------------- */
1556
match_open_bracket();
1557
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1558
QUANTITY_CONTEXT, -1);
1559
match_close_bracket();
1561
AO2.type = VARIABLE_OT; AO2.value = 255; AO2.marker = 0;
1562
assemblez_store(AO2, AO);
1564
parse_code_block(ln = next_label++, continue_label, 1);
1565
assemble_label_no(ln);
1568
/* -------------------------------------------------------------------- */
1569
/* while (<condition>) <codeblock> ------------------------------------ */
1570
/* -------------------------------------------------------------------- */
1573
assemble_label_no(ln = next_label++);
1574
match_open_bracket();
1576
code_generate(parse_expression(CONDITION_CONTEXT),
1577
CONDITION_CONTEXT, ln2 = next_label++);
1578
match_close_bracket();
1580
parse_code_block(ln2, ln, 0);
1581
sequence_point_follows = FALSE;
1583
assemble_label_no(ln2);
1586
/* -------------------------------------------------------------------- */
1589
error("'default' without matching 'switch'"); break;
1591
error("'else' without matching 'if'"); break;
1593
error("'until' without matching 'do'");
1594
panic_mode_error_recovery(); return;
1597
StatementTerminator:
1600
if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
1601
{ ebf_error("';'", token_text);
1606
static void parse_statement_g(int break_label, int continue_label)
1607
{ int ln, ln2, ln3, ln4, flag, onstack;
1608
assembly_operand AO, AO2, AO3, AO4;
1609
dbgl spare_dbgl1, spare_dbgl2;
1613
if ((token_type == SEP_TT) && (token_value == PROPERTY_SEP))
1614
{ /* That is, a full stop, signifying a label */
1617
if (token_type == SYMBOL_TT)
1619
if (sflags[token_value] & UNKNOWN_SFLAG)
1620
{ assign_symbol(token_value, next_label, LABEL_T);
1621
sflags[token_value] |= USED_SFLAG;
1622
assemble_label_no(next_label);
1623
define_symbol_label(token_value);
1627
{ if (stypes[token_value] != LABEL_T) goto LabelError;
1628
if (sflags[token_value] & CHANGE_SFLAG)
1629
{ sflags[token_value] &= (~(CHANGE_SFLAG));
1630
assemble_label_no(svals[token_value]);
1631
define_symbol_label(token_value);
1633
else error_named("Duplicate definition of label:", token_text);
1637
if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
1638
{ ebf_error("';'", token_text);
1639
put_token_back(); return;
1642
/* Interesting point of Inform grammar: a statement can only
1643
consist solely of a label when it is immediately followed
1647
if ((token_type == SEP_TT) && (token_value == CLOSE_BRACE_SEP))
1648
{ put_token_back(); return;
1650
parse_statement(break_label, continue_label);
1653
LabelError: ebf_error("label name", token_text);
1656
if ((token_type == SEP_TT) && (token_value == HASH_SEP))
1657
{ parse_directive(TRUE);
1658
parse_statement(break_label, continue_label); return;
1661
if ((token_type == SEP_TT) && (token_value == AT_SEP))
1662
{ parse_assembly(); return;
1665
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return;
1667
if (token_type == DQ_TT)
1668
{ parse_print_g(TRUE); return;
1671
if ((token_type == SEP_TT) && (token_value == LESS_SEP))
1672
{ parse_action(); goto StatementTerminator; }
1674
if (token_type == EOF_TT)
1675
{ ebf_error("statement", token_text); return; }
1677
if (token_type != STATEMENT_TT)
1679
AO = parse_expression(VOID_CONTEXT);
1680
code_generate(AO, VOID_CONTEXT, -1);
1681
if (vivc_flag) { panic_mode_error_recovery(); return; }
1682
goto StatementTerminator;
1685
statements.enabled = FALSE;
1690
/* -------------------------------------------------------------------- */
1691
/* box <string-1> ... <string-n> -------------------------------------- */
1692
/* -------------------------------------------------------------------- */
1695
AO3.type = CONSTANT_OT;
1696
AO3.value = begin_table_array();
1697
AO3.marker = ARRAY_MV;
1701
if ((token_type==SEP_TT)&&(token_value==SEMICOLON_SEP))
1703
if (token_type != DQ_TT)
1704
ebf_error("text of box line in double-quotes",
1707
for (i=0, j=0; token_text[i] != 0; j++)
1708
if (token_text[i] == '@')
1709
{ if (token_text[i+1] == '@')
1711
while (isdigit(token_text[i])) i++;
1715
if (token_text[i] != 0) i++;
1716
if (token_text[i] != 0) i++;
1720
if (j > ln2) ln2 = j;
1723
array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
1727
error("No lines of text given for 'box' display");
1729
AO2.value = ln2; AO2.marker = 0; set_constant_ot(&AO2);
1730
assembleg_call_2(veneer_routine(Box__Routine_VR),
1731
AO2, AO3, zero_operand);
1734
/* -------------------------------------------------------------------- */
1735
/* break -------------------------------------------------------------- */
1736
/* -------------------------------------------------------------------- */
1739
if (break_label == -1)
1740
error("'break' can only be used in a loop or 'switch' block");
1742
assembleg_jump(break_label);
1745
/* -------------------------------------------------------------------- */
1746
/* continue ----------------------------------------------------------- */
1747
/* -------------------------------------------------------------------- */
1750
if (continue_label == -1)
1751
error("'continue' can only be used in a loop block");
1753
assembleg_jump(continue_label);
1756
/* -------------------------------------------------------------------- */
1757
/* do <codeblock> until (<condition>) --------------------------------- */
1758
/* -------------------------------------------------------------------- */
1761
assemble_label_no(ln = next_label++);
1762
ln2 = next_label++; ln3 = next_label++;
1763
parse_code_block(ln3, ln2, 0);
1764
statements.enabled = TRUE;
1766
if ((token_type == STATEMENT_TT)
1767
&& (token_value == UNTIL_CODE))
1768
{ assemble_label_no(ln2);
1769
match_open_bracket();
1770
AO = parse_expression(CONDITION_CONTEXT);
1771
match_close_bracket();
1772
code_generate(AO, CONDITION_CONTEXT, ln);
1774
else error("'do' without matching 'until'");
1776
assemble_label_no(ln3);
1779
/* -------------------------------------------------------------------- */
1780
/* font on/off -------------------------------------------------------- */
1781
/* -------------------------------------------------------------------- */
1784
misc_keywords.enabled = TRUE;
1786
misc_keywords.enabled = FALSE;
1787
if ((token_type != MISC_KEYWORD_TT)
1788
|| ((token_value != ON_MK)
1789
&& (token_value != OFF_MK)))
1790
{ ebf_error("'on' or 'off'", token_text);
1791
panic_mode_error_recovery();
1795
/* Call glk_set_style(normal or preformatted) */
1798
set_constant_ot(&AO);
1799
if (token_value == ON_MK)
1803
assembleg_call_2(veneer_routine(Glk__Wrap_VR),
1804
AO, AO2, zero_operand);
1807
/* -------------------------------------------------------------------- */
1808
/* for (<initialisation> : <continue-condition> : <updating>) --------- */
1809
/* -------------------------------------------------------------------- */
1811
/* Note that it's legal for any or all of the three sections of a
1812
'for' specification to be empty. This 'for' implementation
1813
often wastes 3 bytes with a redundant branch rather than keep
1814
expression parse trees for long periods (as previous versions
1815
of Inform did, somewhat crudely by simply storing the textual
1816
form of a 'for' loop). It is adequate for now. */
1819
match_open_bracket();
1822
/* Initialisation code */
1824
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
1826
if (!((token_type==SEP_TT)&&(token_value==SUPERCLASS_SEP)))
1827
{ sequence_point_follows = TRUE;
1828
debug_line_ref = token_line_ref;
1829
code_generate(parse_expression(FORINIT_CONTEXT),
1833
if ((token_type==SEP_TT)&&(token_value == SUPERCLASS_SEP))
1835
if ((token_type==SEP_TT)&&(token_value == CLOSEB_SEP))
1836
{ assemble_label_no(ln = next_label++);
1838
parse_code_block(ln2, ln, 0);
1839
sequence_point_follows = FALSE;
1840
if (!execution_never_reaches_here)
1842
assemble_label_no(ln2);
1845
AO.type = OMITTED_OT;
1849
if (!match_colon()) break;
1853
AO.type = OMITTED_OT;
1854
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
1856
spare_dbgl1 = token_line_ref;
1857
AO = parse_expression(CONDITION_CONTEXT);
1858
if (!match_colon()) break;
1863
AO2.type = OMITTED_OT; flag = 0;
1864
if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
1866
spare_dbgl2 = token_line_ref;
1867
AO2 = parse_expression(VOID_CONTEXT);
1868
match_close_bracket();
1869
flag = test_for_incdec(AO2);
1876
if ((AO2.type == OMITTED_OT) || (flag != 0))
1878
assemble_label_no(ln);
1879
if (flag==0) assemble_label_no(ln2);
1881
/* The "finished yet?" condition */
1883
if (AO.type != OMITTED_OT)
1884
{ sequence_point_follows = TRUE;
1885
debug_line_ref = spare_dbgl1;
1886
code_generate(AO, CONDITION_CONTEXT, ln3);
1892
/* This is the jump which could be avoided with the aid
1893
of long-term expression storage */
1895
sequence_point_follows = FALSE;
1896
assembleg_jump(ln2);
1898
/* The "update" part */
1900
assemble_label_no(ln);
1901
sequence_point_follows = TRUE;
1902
debug_line_ref = spare_dbgl2;
1903
code_generate(AO2, VOID_CONTEXT, -1);
1905
assemble_label_no(ln2);
1907
/* The "finished yet?" condition */
1909
if (AO.type != OMITTED_OT)
1910
{ sequence_point_follows = TRUE;
1911
debug_line_ref = spare_dbgl1;
1912
code_generate(AO, CONDITION_CONTEXT, ln3);
1918
/* In this optimised case, update code is at the end
1919
of the loop block, so "continue" goes there */
1921
parse_code_block(ln3, ln2, 0);
1922
assemble_label_no(ln2);
1924
sequence_point_follows = TRUE;
1925
debug_line_ref = spare_dbgl2;
1928
if (AO3.value >= MAX_LOCAL_VARIABLES)
1929
AO3.type = GLOBALVAR_OT;
1931
AO3.type = LOCALVAR_OT;
1933
assembleg_3(add_gc, AO3, one_operand, AO3);
1936
{ AO3.value = -flag;
1937
if (AO3.value >= MAX_LOCAL_VARIABLES)
1938
AO3.type = GLOBALVAR_OT;
1940
AO3.type = LOCALVAR_OT;
1942
assembleg_3(sub_gc, AO3, one_operand, AO3);
1948
/* In the unoptimised case, update code is at the
1949
start of the loop block, so "continue" goes there */
1951
parse_code_block(ln3, ln, 0);
1952
if (!execution_never_reaches_here)
1953
{ sequence_point_follows = FALSE;
1958
assemble_label_no(ln3);
1961
/* -------------------------------------------------------------------- */
1962
/* give <expression> [~]attr [, [~]attr [, ...]] ---------------------- */
1963
/* -------------------------------------------------------------------- */
1966
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1967
QUANTITY_CONTEXT, -1);
1968
if ((AO.type == LOCALVAR_OT) && (AO.value == 0))
1975
if ((token_type == SEP_TT)
1976
&& (token_value == SEMICOLON_SEP)) {
1978
assembleg_2(copy_gc, stack_pointer, zero_operand);
1982
if ((token_type == SEP_TT)&&(token_value == ARTNOT_SEP))
1985
{ if ((token_type == SYMBOL_TT)
1986
&& (stypes[token_value] != ATTRIBUTE_T))
1987
warning_named("This is not a declared Attribute:",
1992
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1993
QUANTITY_CONTEXT, -1);
1994
if (runtime_error_checking_switch && (!veneer_mode))
1995
{ ln2 = (ln ? RT__ChG_VR : RT__ChGt_VR);
1996
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0)) {
1997
/* already on stack */
2000
assembleg_store(stack_pointer, AO2);
2003
assembleg_2(stkpeek_gc, one_operand, stack_pointer);
2005
assembleg_store(stack_pointer, AO);
2006
assembleg_3(call_gc, veneer_routine(ln2), two_operand,
2010
if (is_constant_ot(AO2.type) && AO2.marker == 0) {
2012
set_constant_ot(&AO2);
2017
AO3.type = BYTECONSTANT_OT;
2018
assembleg_3(add_gc, AO2, AO3, stack_pointer);
2019
AO2 = stack_pointer;
2022
if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0))
2023
assembleg_2(stkpeek_gc, one_operand,
2026
assembleg_2(stkpeek_gc, zero_operand,
2033
assembleg_3(astorebit_gc, AO, AO2, AO3);
2037
/* -------------------------------------------------------------------- */
2038
/* if (<condition>) <codeblock> [else <codeblock>] -------------------- */
2039
/* -------------------------------------------------------------------- */
2044
match_open_bracket();
2045
AO = parse_expression(CONDITION_CONTEXT);
2046
match_close_bracket();
2048
statements.enabled = TRUE;
2050
if ((token_type == STATEMENT_TT)&&(token_value == RTRUE_CODE))
2053
if ((token_type == STATEMENT_TT)&&(token_value == RFALSE_CODE))
2060
code_generate(AO, CONDITION_CONTEXT, ln);
2062
if (ln >= 0) parse_code_block(break_label, continue_label, 0);
2065
if ((token_type != SEP_TT)
2066
|| (token_value != SEMICOLON_SEP))
2067
{ ebf_error("';'", token_text);
2072
statements.enabled = TRUE;
2074
if ((token_type == STATEMENT_TT) && (token_value == ELSE_CODE))
2077
{ ln2 = next_label++;
2078
if (!execution_never_reaches_here)
2079
{ sequence_point_follows = FALSE;
2080
assembleg_jump(ln2);
2084
else put_token_back();
2086
if (ln >= 0) assemble_label_no(ln);
2089
{ parse_code_block(break_label, continue_label, 0);
2090
if (ln >= 0) assemble_label_no(ln2);
2095
/* -------------------------------------------------------------------- */
2096
/* inversion ---------------------------------------------------------- */
2097
/* -------------------------------------------------------------------- */
2099
case INVERSION_CODE:
2101
AO2.type = DEREFERENCE_OT;
2102
AO2.value = GLULX_HEADER_SIZE+8;
2103
assembleg_2(copyb_gc, AO2, stack_pointer);
2104
assembleg_1(streamchar_gc, stack_pointer);
2105
AO2.value = GLULX_HEADER_SIZE+9;
2106
assembleg_2(copyb_gc, AO2, stack_pointer);
2107
assembleg_1(streamchar_gc, stack_pointer);
2108
AO2.value = GLULX_HEADER_SIZE+10;
2109
assembleg_2(copyb_gc, AO2, stack_pointer);
2110
assembleg_1(streamchar_gc, stack_pointer);
2111
AO2.value = GLULX_HEADER_SIZE+11;
2112
assembleg_2(copyb_gc, AO2, stack_pointer);
2113
assembleg_1(streamchar_gc, stack_pointer);
2118
set_constant_ot(&AO);
2119
assembleg_1(streamchar_gc, AO);
2121
set_constant_ot(&AO);
2122
assembleg_1(streamchar_gc, AO);
2124
AO2.value = GLULX_HEADER_SIZE+12;
2125
assembleg_2(copyb_gc, AO2, stack_pointer);
2126
assembleg_1(streamchar_gc, stack_pointer);
2127
AO2.value = GLULX_HEADER_SIZE+13;
2128
assembleg_2(copyb_gc, AO2, stack_pointer);
2129
assembleg_1(streamchar_gc, stack_pointer);
2130
AO2.value = GLULX_HEADER_SIZE+14;
2131
assembleg_2(copyb_gc, AO2, stack_pointer);
2132
assembleg_1(streamchar_gc, stack_pointer);
2133
AO2.value = GLULX_HEADER_SIZE+15;
2134
assembleg_2(copyb_gc, AO2, stack_pointer);
2135
assembleg_1(streamchar_gc, stack_pointer);
2139
set_constant_ot(&AO);
2140
assembleg_1(streamchar_gc, AO);
2145
/* -------------------------------------------------------------------- */
2146
/* jump <label> ------------------------------------------------------- */
2147
/* -------------------------------------------------------------------- */
2150
assembleg_jump(parse_label());
2153
/* -------------------------------------------------------------------- */
2154
/* move <expression> to <expression> ---------------------------------- */
2155
/* -------------------------------------------------------------------- */
2158
misc_keywords.enabled = TRUE;
2159
AO = parse_expression(QUANTITY_CONTEXT);
2162
misc_keywords.enabled = FALSE;
2163
if ((token_type != MISC_KEYWORD_TT)
2164
|| (token_value != TO_MK))
2165
{ ebf_error("'to'", token_text);
2166
panic_mode_error_recovery();
2170
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2171
QUANTITY_CONTEXT, -1);
2172
AO = code_generate(AO, QUANTITY_CONTEXT, -1);
2173
if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
2174
assembleg_call_2(veneer_routine(RT__ChT_VR), AO, AO2,
2177
assembleg_call_2(veneer_routine(OB__Move_VR), AO, AO2,
2181
/* -------------------------------------------------------------------- */
2182
/* new_line ----------------------------------------------------------- */
2183
/* -------------------------------------------------------------------- */
2186
AO.type = BYTECONSTANT_OT; AO.value = 0x0A; AO.marker = 0;
2187
assembleg_1(streamchar_gc, AO);
2190
/* -------------------------------------------------------------------- */
2191
/* objectloop (<initialisation>) <codeblock> -------------------------- */
2192
/* -------------------------------------------------------------------- */
2194
case OBJECTLOOP_CODE:
2196
match_open_bracket();
2198
if (token_type == LOCAL_VARIABLE_TT) {
2199
AO.value = token_value;
2200
AO.type = LOCALVAR_OT;
2203
else if ((token_type == SYMBOL_TT) &&
2204
(stypes[token_value] == GLOBAL_VARIABLE_T)) {
2205
AO.value = svals[token_value];
2206
AO.type = GLOBALVAR_OT;
2210
ebf_error("'objectloop' variable", token_text);
2211
panic_mode_error_recovery();
2214
/*if ((module_switch)
2215
&& (AO.value >= MAX_LOCAL_VARIABLES)
2216
&& (AO.value < LOWEST_SYSTEM_VAR_NUMBER))
2217
AO.marker = VARIABLE_MV;
2218
else AO.marker = 0;*/
2219
misc_keywords.enabled = TRUE;
2220
get_next_token(); flag = TRUE;
2221
misc_keywords.enabled = FALSE;
2222
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
2226
if ((token_type == MISC_KEYWORD_TT)
2227
&& (token_value == NEAR_MK)) ln = 1;
2228
if ((token_type == MISC_KEYWORD_TT)
2229
&& (token_value == FROM_MK)) ln = 2;
2230
if ((token_type == CND_TT) && (token_value == IN_COND))
2233
if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
2240
/* Old style (Inform 5) objectloops: note that we
2241
implement objectloop (a in b) in the old way since
2242
this runs through objects in a different order from
2243
the new way, and there may be existing Inform code
2245
assembly_operand AO4, AO5;
2247
sequence_point_follows = TRUE;
2248
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2249
QUANTITY_CONTEXT, -1);
2250
match_close_bracket();
2252
if (runtime_error_checking_switch)
2253
AO2 = check_nonzero_at_runtime(AO2, -1,
2255
AO4.type = BYTECONSTANT_OT;
2256
AO4.value = 5; /* parent */
2258
assembleg_3(aload_gc, AO2, AO4, stack_pointer);
2259
AO4.type = BYTECONSTANT_OT;
2260
AO4.value = 7; /* child */
2262
assembleg_3(aload_gc, stack_pointer, AO4, stack_pointer);
2263
AO2 = stack_pointer;
2266
if (runtime_error_checking_switch) {
2268
AO2 = check_nonzero_at_runtime(AO2, -1,
2271
AO4.type = BYTECONSTANT_OT;
2272
AO4.value = 7; /* child */
2274
assembleg_3(aload_gc, AO2, AO4, stack_pointer);
2275
AO2 = stack_pointer;
2280
assembleg_store(AO, AO2);
2281
assembleg_1_branch(jz_gc, AO, ln2 = next_label++);
2282
assemble_label_no(ln4 = next_label++);
2283
parse_code_block(ln2, ln3 = next_label++, 0);
2284
sequence_point_follows = FALSE;
2285
assemble_label_no(ln3);
2286
if (runtime_error_checking_switch) {
2287
AO2 = check_nonzero_at_runtime(AO, ln2,
2290
&& ((AO5.type != LOCALVAR_OT)||(AO5.value != 0))
2291
&& ((AO5.type != LOCALVAR_OT)||(AO5.value != AO.value)))
2292
{ assembly_operand en_ao;
2293
en_ao.value = OBJECTLOOP_BROKEN_RTE;
2295
set_constant_ot(&en_ao);
2296
AO4.type = BYTECONSTANT_OT;
2297
AO4.value = 5; /* parent */
2299
assembleg_3(aload_gc, AO, AO4, stack_pointer);
2300
assembleg_2_branch(jeq_gc, stack_pointer, AO5,
2302
assembleg_call_2(veneer_routine(RT__Err_VR),
2303
en_ao, AO, zero_operand);
2304
assembleg_jump(ln2);
2305
assemble_label_no(next_label++);
2311
AO4.type = BYTECONSTANT_OT;
2312
AO4.value = 6; /* sibling */
2314
assembleg_3(aload_gc, AO2, AO4, AO);
2315
assembleg_1_branch(jnz_gc, AO, ln4);
2316
assemble_label_no(ln2);
2320
sequence_point_follows = TRUE;
2321
ln = symbol_index("Class", -1);
2322
AO2.value = svals[ln];
2323
AO2.marker = OBJECT_MV;
2324
AO2.type = CONSTANT_OT;
2325
assembleg_store(AO, AO2);
2327
assemble_label_no(ln = next_label++);
2333
sequence_point_follows = TRUE;
2334
code_generate(parse_expression(CONDITION_CONTEXT),
2335
CONDITION_CONTEXT, ln3);
2336
match_close_bracket();
2338
parse_code_block(ln2, ln3, 0);
2340
sequence_point_follows = FALSE;
2341
assemble_label_no(ln3);
2342
assembleg_3(aload_gc, AO, two_operand, AO);
2343
assembleg_1_branch(jnz_gc, AO, ln);
2344
assemble_label_no(ln2);
2347
/* -------------------------------------------------------------------- */
2348
/* (see routine above) ------------------------------------------------ */
2349
/* -------------------------------------------------------------------- */
2353
parse_print_g(FALSE); return;
2354
case PRINT_RET_CODE:
2356
parse_print_g(TRUE); return;
2358
/* -------------------------------------------------------------------- */
2359
/* quit --------------------------------------------------------------- */
2360
/* -------------------------------------------------------------------- */
2363
assembleg_0(quit_gc); break;
2365
/* -------------------------------------------------------------------- */
2366
/* remove <expression> ------------------------------------------------ */
2367
/* -------------------------------------------------------------------- */
2370
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2371
QUANTITY_CONTEXT, -1);
2372
if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
2373
assembleg_call_1(veneer_routine(RT__ChR_VR), AO,
2376
assembleg_call_1(veneer_routine(OB__Remove_VR), AO,
2380
/* -------------------------------------------------------------------- */
2381
/* return [<expression>] ---------------------------------------------- */
2382
/* -------------------------------------------------------------------- */
2386
if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
2387
AO.type = BYTECONSTANT_OT; AO.value = 1; AO.marker = 0;
2388
assembleg_1(return_gc, AO);
2392
AO = code_generate(parse_expression(RETURN_Q_CONTEXT),
2393
QUANTITY_CONTEXT, -1);
2394
assembleg_1(return_gc, AO);
2397
/* -------------------------------------------------------------------- */
2398
/* rfalse ------------------------------------------------------------- */
2399
/* -------------------------------------------------------------------- */
2402
assembleg_1(return_gc, zero_operand);
2405
/* -------------------------------------------------------------------- */
2406
/* rtrue -------------------------------------------------------------- */
2407
/* -------------------------------------------------------------------- */
2410
assembleg_1(return_gc, one_operand);
2413
/* -------------------------------------------------------------------- */
2414
/* spaces <expression> ------------------------------------------------ */
2415
/* -------------------------------------------------------------------- */
2418
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2419
QUANTITY_CONTEXT, -1);
2421
assembleg_store(temp_var1, AO);
2423
AO.value = 32; AO.marker = 0; set_constant_ot(&AO);
2425
assembleg_2_branch(jlt_gc, temp_var1, one_operand,
2427
assemble_label_no(ln2 = next_label++);
2428
assembleg_1(streamchar_gc, AO);
2429
assembleg_dec(temp_var1);
2430
assembleg_1_branch(jnz_gc, temp_var1, ln2);
2431
assemble_label_no(ln);
2434
/* -------------------------------------------------------------------- */
2435
/* string <expression> <literal-string> ------------------------------- */
2436
/* -------------------------------------------------------------------- */
2439
AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2440
QUANTITY_CONTEXT, -1);
2442
if (token_type == DQ_TT)
2443
{ AO4.value = compile_string(token_text, TRUE, TRUE);
2444
AO4.marker = STRING_MV;
2445
AO4.type = CONSTANT_OT;
2449
AO4 = parse_expression(CONSTANT_CONTEXT);
2451
assembleg_call_2(veneer_routine(Dynam__String_VR),
2452
AO2, AO4, zero_operand);
2455
/* -------------------------------------------------------------------- */
2456
/* style roman/reverse/bold/underline/fixed --------------------------- */
2457
/* -------------------------------------------------------------------- */
2460
misc_keywords.enabled = TRUE;
2462
misc_keywords.enabled = FALSE;
2463
if ((token_type != MISC_KEYWORD_TT)
2464
|| ((token_value != ROMAN_MK)
2465
&& (token_value != REVERSE_MK)
2466
&& (token_value != BOLD_MK)
2467
&& (token_value != UNDERLINE_MK)
2468
&& (token_value != FIXED_MK)))
2470
"'roman', 'bold', 'underline', 'reverse' or 'fixed'",
2472
panic_mode_error_recovery();
2476
/* Call glk_set_style() */
2480
set_constant_ot(&AO);
2483
AO2 = zero_operand; /* normal */
2486
AO2.value = 5; /* alert */
2488
set_constant_ot(&AO2);
2491
AO2.value = 4; /* subheader */
2493
set_constant_ot(&AO2);
2496
AO2 = one_operand; /* emphasized */
2499
AO2 = two_operand; /* preformatted */
2502
assembleg_call_2(veneer_routine(Glk__Wrap_VR),
2503
AO, AO2, zero_operand);
2506
/* -------------------------------------------------------------------- */
2507
/* switch (<expression>) <codeblock> ---------------------------------- */
2508
/* -------------------------------------------------------------------- */
2511
match_open_bracket();
2512
AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2513
QUANTITY_CONTEXT, -1);
2514
match_close_bracket();
2516
assembleg_store(temp_var1, AO);
2518
parse_code_block(ln = next_label++, continue_label, 1);
2519
assemble_label_no(ln);
2522
/* -------------------------------------------------------------------- */
2523
/* while (<condition>) <codeblock> ------------------------------------ */
2524
/* -------------------------------------------------------------------- */
2527
assemble_label_no(ln = next_label++);
2528
match_open_bracket();
2530
code_generate(parse_expression(CONDITION_CONTEXT),
2531
CONDITION_CONTEXT, ln2 = next_label++);
2532
match_close_bracket();
2534
parse_code_block(ln2, ln, 0);
2535
sequence_point_follows = FALSE;
2537
assemble_label_no(ln2);
2540
/* -------------------------------------------------------------------- */
2543
error("'default' without matching 'switch'"); break;
2545
error("'else' without matching 'if'"); break;
2547
error("'until' without matching 'do'");
2548
panic_mode_error_recovery(); return;
2550
/* -------------------------------------------------------------------- */
2552
/* And a useful default, which will never be triggered in a complete
2553
Inform compiler, but which is important in development. */
2556
error("*** Statement code gen: Can't generate yet ***\n");
2557
panic_mode_error_recovery(); return;
2560
StatementTerminator:
2563
if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
2564
{ ebf_error("';'", token_text);
2569
extern void parse_statement(int break_label, int continue_label)
2572
parse_statement_z(break_label, continue_label);
2574
parse_statement_g(break_label, continue_label);
2577
/* ========================================================================= */
2578
/* Data structure management routines */
2579
/* ------------------------------------------------------------------------- */
2581
extern void init_states_vars(void)
2585
extern void states_begin_pass(void)
2589
extern void states_allocate_arrays(void)
2593
extern void states_free_arrays(void)
2597
/* ========================================================================= */