1 /* ------------------------------------------------------------------------- */
2 /* "expressp" : The expression parser */
4 /* Copyright (c) Graham Nelson 1993 - 2020 */
6 /* This file is part of Inform. */
8 /* Inform is free software: you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation, either version 3 of the License, or */
11 /* (at your option) any later version. */
13 /* Inform is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with Inform. If not, see https://gnu.org/licenses/ */
21 /* ------------------------------------------------------------------------- */
25 /* --- Interface to lexer -------------------------------------------------- */
27 static char separators_to_operators[103];
28 static char conditionals_to_operators[7];
29 static char token_type_allowable[301];
31 #define NOT_AN_OPERATOR (char) 0x7e
33 static void make_lexical_interface_tables(void)
36 separators_to_operators[i] = NOT_AN_OPERATOR;
37 for (i=0;i<NUM_OPERATORS;i++)
38 if (operators[i].token_type == SEP_TT)
39 separators_to_operators[operators[i].token_value] = i;
41 for (i=0;i<7;i++) /* 7 being the size of keyword_group "conditions" */
42 conditionals_to_operators[i] = NOT_AN_OPERATOR;
43 for (i=0;i<NUM_OPERATORS;i++)
44 if (operators[i].token_type == CND_TT)
45 conditionals_to_operators[operators[i].token_value] = i;
47 for (i=0;i<301;i++) token_type_allowable[i] = 0;
49 token_type_allowable[VARIABLE_TT] = 1;
50 token_type_allowable[SYSFUN_TT] = 1;
51 token_type_allowable[DQ_TT] = 1;
52 token_type_allowable[DICTWORD_TT] = 1;
53 token_type_allowable[SUBOPEN_TT] = 1;
54 token_type_allowable[SUBCLOSE_TT] = 1;
55 token_type_allowable[SMALL_NUMBER_TT] = 1;
56 token_type_allowable[LARGE_NUMBER_TT] = 1;
57 token_type_allowable[ACTION_TT] = 1;
58 token_type_allowable[SYSTEM_CONSTANT_TT] = 1;
59 token_type_allowable[OP_TT] = 1;
62 static token_data current_token, previous_token, heldback_token;
64 static int comma_allowed, arrow_allowed, superclass_allowed,
66 array_init_ambiguity, action_ambiguity,
67 etoken_count, inserting_token, bracket_level;
69 extern int *variable_usage;
71 int system_function_usage[32];
73 static int get_next_etoken(void)
74 { int v, symbol = 0, mark_symbol_as_used = FALSE,
75 initial_bracket_level = bracket_level;
80 { current_token = heldback_token;
81 inserting_token = FALSE;
85 current_token.text = token_text;
86 current_token.value = token_value;
87 current_token.type = token_type;
88 current_token.marker = 0;
89 current_token.symtype = 0;
90 current_token.symflags = -1;
93 switch(current_token.type)
94 { case LOCAL_VARIABLE_TT:
95 current_token.type = VARIABLE_TT;
96 variable_usage[current_token.value] = TRUE;
100 current_token.marker = STRING_MV;
104 { int32 unicode = text_to_unicode(token_text);
105 if (token_text[textual_form_length] == 0)
108 current_token.value = unicode_to_zscii(unicode);
109 if (current_token.value == 5)
110 { unicode_char_error("Character can be printed \
111 but not used as a value:", unicode);
112 current_token.value = '?';
114 if (current_token.value >= 0x100)
115 current_token.type = LARGE_NUMBER_TT;
116 else current_token.type = SMALL_NUMBER_TT;
119 current_token.value = unicode;
120 if (current_token.value >= 0x8000
121 || current_token.value < -0x8000)
122 current_token.type = LARGE_NUMBER_TT;
123 else current_token.type = SMALL_NUMBER_TT;
127 { current_token.type = DICTWORD_TT;
128 current_token.marker = DWORD_MV;
135 symbol = current_token.value;
137 mark_symbol_as_used = TRUE;
141 current_token.symtype = stypes[symbol];
142 current_token.symflags = sflags[symbol];
143 switch(stypes[symbol])
145 /* Replaced functions must always be backpatched
146 because there could be another definition coming. */
147 if (sflags[symbol] & REPLACE_SFLAG)
148 { current_token.marker = SYMBOL_MV;
149 if (module_switch) import_symbol(symbol);
153 current_token.marker = IROUTINE_MV;
155 case GLOBAL_VARIABLE_T:
156 current_token.marker = VARIABLE_MV;
160 /* All objects must be backpatched in Glulx. */
161 if (module_switch || glulx_mode)
162 current_token.marker = OBJECT_MV;
165 current_token.marker = ARRAY_MV;
168 current_token.marker = STATIC_ARRAY_MV;
170 case INDIVIDUAL_PROPERTY_T:
171 if (module_switch) current_token.marker = IDENT_MV;
174 if (sflags[symbol] & (UNKNOWN_SFLAG + CHANGE_SFLAG))
175 { current_token.marker = SYMBOL_MV;
176 if (module_switch) import_symbol(symbol);
179 else current_token.marker = 0;
182 error_named("Label name used as value:", token_text);
185 current_token.marker = 0;
188 if (sflags[symbol] & SYSTEM_SFLAG)
189 current_token.marker = 0;
191 current_token.value = v;
194 if (((current_token.marker != 0)
195 && (current_token.marker != VARIABLE_MV))
196 || (v < 0) || (v > 255))
197 current_token.type = LARGE_NUMBER_TT;
198 else current_token.type = SMALL_NUMBER_TT;
201 if (((current_token.marker != 0)
202 && (current_token.marker != VARIABLE_MV))
203 || (v < -0x8000) || (v >= 0x8000))
204 current_token.type = LARGE_NUMBER_TT;
205 else current_token.type = SMALL_NUMBER_TT;
208 if (stypes[symbol] == GLOBAL_VARIABLE_T)
209 { current_token.type = VARIABLE_TT;
210 variable_usage[current_token.value] = TRUE;
216 if (current_token.value >= 256)
217 current_token.type = LARGE_NUMBER_TT;
219 current_token.type = SMALL_NUMBER_TT;
222 if (current_token.value < -0x8000
223 || current_token.value >= 0x8000)
224 current_token.type = LARGE_NUMBER_TT;
226 current_token.type = SMALL_NUMBER_TT;
231 switch(current_token.value)
234 current_token.type = ENDEXP_TT;
238 if ((bracket_level==0) && (!comma_allowed))
239 current_token.type = ENDEXP_TT;
243 if ((bracket_level==0) && (!superclass_allowed))
244 current_token.type = ENDEXP_TT;
249 if ((token_type == SEP_TT)
250 &&((token_value == SEMICOLON_SEP)
251 || (token_value == GREATER_SEP)))
252 current_token.type = ENDEXP_TT;
258 if (expr_trace_level>=3)
259 { printf("Previous token type = %d\n",previous_token.type);
260 printf("Previous token val = %d\n",previous_token.value);
262 if ((previous_token.type == OP_TT)
263 || (previous_token.type == SUBOPEN_TT)
264 || (previous_token.type == ENDEXP_TT)
265 || (array_init_ambiguity)
266 || ((bracket_level == 1) && (action_ambiguity)))
267 current_token.type = SUBOPEN_TT;
269 { inserting_token = TRUE;
270 heldback_token = current_token;
271 current_token.text = "<call>";
278 if (bracket_level < 0)
279 current_token.type = ENDEXP_TT;
280 else current_token.type = SUBCLOSE_TT;
284 current_token.type = ENDEXP_TT; break;
287 if ((previous_token.type == OP_TT)
288 || (previous_token.type == SUBOPEN_TT)
289 || (previous_token.type == ENDEXP_TT))
290 current_token.value = UNARY_MINUS_SEP; break;
293 if ((previous_token.type == VARIABLE_TT)
294 || (previous_token.type == SUBCLOSE_TT)
295 || (previous_token.type == LARGE_NUMBER_TT)
296 || (previous_token.type == SMALL_NUMBER_TT))
297 current_token.value = POST_INC_SEP; break;
300 if ((previous_token.type == VARIABLE_TT)
301 || (previous_token.type == SUBCLOSE_TT)
302 || (previous_token.type == LARGE_NUMBER_TT)
303 || (previous_token.type == SMALL_NUMBER_TT))
304 current_token.value = POST_DEC_SEP; break;
307 token_text = current_token.text + 2;
309 ActionUsedAsConstant:
311 current_token.type = ACTION_TT;
312 current_token.text = token_text;
313 current_token.value = 0;
314 current_token.marker = ACTION_MV;
318 case HASHADOLLAR_SEP:
319 obsolete_warning("'#a$Act' is now superseded by '##Act'");
320 token_text = current_token.text + 3;
321 goto ActionUsedAsConstant;
323 case HASHGDOLLAR_SEP:
325 /* This form generates the position of a global variable
326 in the global variables array. So Glob is the same as
327 #globals_array --> #g$Glob */
329 current_token.text += 3;
330 current_token.type = SYMBOL_TT;
331 symbol = symbol_index(current_token.text, -1);
332 if (stypes[symbol] != GLOBAL_VARIABLE_T) {
334 "global variable name after '#g$'",
336 current_token.value = 0;
337 current_token.type = SMALL_NUMBER_TT;
338 current_token.marker = 0;
341 mark_symbol_as_used = TRUE;
342 current_token.value = svals[symbol] - MAX_LOCAL_VARIABLES;
343 current_token.marker = 0;
345 if (current_token.value >= 0x100)
346 current_token.type = LARGE_NUMBER_TT;
347 else current_token.type = SMALL_NUMBER_TT;
350 if (current_token.value >= 0x8000
351 || current_token.value < -0x8000)
352 current_token.type = LARGE_NUMBER_TT;
353 else current_token.type = SMALL_NUMBER_TT;
357 case HASHNDOLLAR_SEP:
359 /* This form is still needed for constants like #n$a (the
360 dictionary address of the word "a"), since 'a' means
361 the ASCII value of 'a' */
363 if (strlen(token_text) > 4)
365 "'#n$word' is now superseded by ''word''");
366 current_token.type = DICTWORD_TT;
367 current_token.value = 0;
368 current_token.text = token_text + 3;
369 current_token.marker = DWORD_MV;
372 case HASHRDOLLAR_SEP:
374 /* This form -- #r$Routinename, to return the routine's */
375 /* packed address -- is needed far less often in Inform 6, */
376 /* where just giving the name Routine returns the packed */
377 /* address. But it's used in a lot of Inform 5 code. */
380 "'#r$Routine' can now be written just 'Routine'");
381 current_token.text += 3;
382 current_token.type = SYMBOL_TT;
383 current_token.value = symbol_index(current_token.text, -1);
386 case HASHWDOLLAR_SEP:
387 error("The obsolete '#w$word' construct has been removed");
391 system_constants.enabled = TRUE;
393 system_constants.enabled = FALSE;
394 if (token_type != SYSTEM_CONSTANT_TT)
396 "'r$', 'n$', 'g$' or internal Inform constant name after '#'",
401 { current_token.type = token_type;
402 current_token.value = token_value;
403 current_token.text = token_text;
404 current_token.marker = INCON_MV;
411 v = conditionals_to_operators[current_token.value];
412 if (v != NOT_AN_OPERATOR)
413 { current_token.type = OP_TT; current_token.value = v;
418 if (current_token.type == SEP_TT)
419 { v = separators_to_operators[current_token.value];
420 if (v != NOT_AN_OPERATOR)
422 || ((v!=MESSAGE_OP) && (v!=MPROP_NUM_OP) && (v!=MPROP_NUM_OP)))
423 { current_token.type = OP_TT; current_token.value = v;
424 if (array_init_ambiguity &&
425 ((v==MINUS_OP) || (v==UNARY_MINUS_OP)) &&
426 (initial_bracket_level == 0) &&
428 warning("Without bracketing, the minus sign '-' is ambiguous");
433 /* A feature of Inform making it annoyingly hard to parse left-to-right
434 is that there is no clear delimiter for expressions; that is, the
435 legal syntax often includes sequences of expressions with no
436 intervening markers such as commas. We therefore need to use some
437 internal context to determine whether an end is in sight... */
439 if (token_type_allowable[current_token.type]==0)
440 { if (expr_trace_level >= 3)
441 { printf("Discarding as not allowable: '%s' ", current_token.text);
442 describe_token(current_token);
445 current_token.type = ENDEXP_TT;
448 if ((!((initial_bracket_level > 0)
449 || (previous_token.type == ENDEXP_TT)
450 || ((previous_token.type == OP_TT)
451 && (operators[previous_token.value].usage != POST_U))
452 || (previous_token.type == SYSFUN_TT)))
453 && ((current_token.type != OP_TT)
454 || (operators[current_token.value].usage == PRE_U)))
455 { if (expr_trace_level >= 3)
456 { printf("Discarding as no longer part: '%s' ", current_token.text);
457 describe_token(current_token);
460 current_token.type = ENDEXP_TT;
463 { if (mark_symbol_as_used) sflags[symbol] |= USED_SFLAG;
464 if (expr_trace_level >= 3)
465 { printf("Expr token = '%s' ", current_token.text);
466 describe_token(current_token);
471 if ((previous_token.type == ENDEXP_TT)
472 && (current_token.type == ENDEXP_TT)) return FALSE;
474 previous_token = current_token;
479 /* --- Operator precedences ------------------------------------------------ */
483 #define GREATER_P 103
485 #define e1 1 /* Missing operand error */
486 #define e2 2 /* Unexpected close bracket */
487 #define e3 3 /* Missing operator error */
488 #define e4 4 /* Expression ends with an open bracket */
489 #define e5 5 /* Associativity illegal error */
491 const int prec_table[] = {
493 /* a .......... ( ) end op term */
495 /* b ( */ LOWER_P, e3, LOWER_P, LOWER_P, e3,
496 /* . ) */ EQUAL_P, GREATER_P, e2, GREATER_P, GREATER_P,
497 /* . end */ e4, GREATER_P, e1, GREATER_P, GREATER_P,
498 /* . op */ LOWER_P, GREATER_P, LOWER_P, -1, GREATER_P,
499 /* . term */ LOWER_P, e3, LOWER_P, LOWER_P, e3
503 static int find_prec(token_data a, token_data b)
505 /* We are comparing the precedence of tokens a and b
506 (where a occurs to the left of b). If the expression is correct,
507 the only possible values are GREATER_P, LOWER_P or EQUAL_P;
508 if it is malformed then one of e1 to e5 results.
510 Note that this routine is not symmetrical and that the relation
513 If a and b are equal (and aren't brackets), then
515 a LOWER_P a if a right-associative
516 a GREATER_P a if a left-associative
522 { case SUBOPEN_TT: i=0; break;
523 case SUBCLOSE_TT: i=1; break;
524 case ENDEXP_TT: i=2; break;
525 case OP_TT: i=3; break;
529 { case SUBOPEN_TT: i+=0; break;
530 case SUBCLOSE_TT: i+=5; break;
531 case ENDEXP_TT: i+=10; break;
532 case OP_TT: i+=15; break;
533 default: i+=20; break;
536 j = prec_table[i]; if (j != -1) return j;
538 l1 = operators[a.value].precedence;
539 l2 = operators[b.value].precedence;
540 if (operators[b.value].usage == PRE_U) return LOWER_P;
541 if (operators[a.value].usage == POST_U) return GREATER_P;
543 /* Anomalous rule to resolve the function call precedence, which is
544 different on the right from on the left, e.g., in:
550 if ((l1 == 11) && (l2 > 11)) return GREATER_P;
552 if (l1 < l2) return LOWER_P;
553 if (l1 > l2) return GREATER_P;
554 switch(operators[a.value].associativity)
555 { case L_A: return GREATER_P;
556 case R_A: return LOWER_P;
562 /* --- Converting token to operand ----------------------------------------- */
564 /* Must match the switch statement below */
565 int z_system_constant_list[] =
566 { adjectives_table_SC,
569 identifiers_table_SC,
574 actual_largest_object_SC,
575 static_memory_offset_SC,
576 array_names_offset_SC,
577 readable_memory_offset_SC,
584 highest_attribute_number_SC,
585 attribute_names_array_SC,
586 highest_property_number_SC,
587 property_names_array_SC,
588 highest_action_number_SC,
589 action_names_array_SC,
590 highest_fake_action_number_SC,
591 fake_action_names_array_SC,
592 highest_routine_number_SC,
593 routine_names_array_SC,
595 routine_flags_array_SC,
596 highest_global_number_SC,
597 global_names_array_SC,
599 global_flags_array_SC,
600 highest_array_number_SC,
601 array_names_array_SC,
602 array_flags_array_SC,
603 highest_constant_number_SC,
604 constant_names_array_SC,
605 highest_class_number_SC,
606 class_objects_array_SC,
607 highest_object_number_SC,
610 static int32 value_of_system_constant_z(int t)
612 { case adjectives_table_SC:
613 return adjectives_offset;
614 case actions_table_SC:
615 return actions_offset;
616 case classes_table_SC:
617 return class_numbers_offset;
618 case identifiers_table_SC:
619 return identifier_names_offset;
620 case preactions_table_SC:
621 return preactions_offset;
622 case largest_object_SC:
623 return 256 + no_objects - 1;
624 case strings_offset_SC:
625 return strings_offset/scale_factor;
627 return code_offset/scale_factor;
628 case actual_largest_object_SC:
630 case static_memory_offset_SC:
631 return static_memory_offset;
632 case array_names_offset_SC:
633 return array_names_offset;
634 case readable_memory_offset_SC:
635 return Write_Code_At;
637 return prop_values_offset;
639 return class_numbers_offset;
641 return individuals_offset;
643 return variables_offset;
644 case array__start_SC:
645 return variables_offset + (MAX_GLOBAL_VARIABLES*WORDSIZE);
647 return static_memory_offset;
649 case highest_attribute_number_SC:
650 return no_attributes-1;
651 case attribute_names_array_SC:
652 return attribute_names_offset;
654 case highest_property_number_SC:
655 return no_individual_properties-1;
656 case property_names_array_SC:
657 return identifier_names_offset + 2;
659 case highest_action_number_SC:
661 case action_names_array_SC:
662 return action_names_offset;
664 case highest_fake_action_number_SC:
665 return ((grammar_version_number==1)?256:4096) + no_fake_actions-1;
666 case fake_action_names_array_SC:
667 return fake_action_names_offset;
669 case highest_routine_number_SC:
670 return no_named_routines-1;
671 case routine_names_array_SC:
672 return routine_names_offset;
673 case routines_array_SC:
674 return routines_array_offset;
675 case routine_flags_array_SC:
676 return routine_flags_array_offset;
677 case highest_global_number_SC:
678 return 16 + no_globals-1;
679 case global_names_array_SC:
680 return global_names_offset;
681 case globals_array_SC:
682 return variables_offset;
683 case global_flags_array_SC:
684 return global_flags_array_offset;
685 case highest_array_number_SC:
687 case array_names_array_SC:
688 return array_names_offset;
689 case array_flags_array_SC:
690 return array_flags_array_offset;
691 case highest_constant_number_SC:
692 return no_named_constants-1;
693 case constant_names_array_SC:
694 return constant_names_offset;
695 case highest_class_number_SC:
697 case class_objects_array_SC:
698 return class_numbers_offset;
699 case highest_object_number_SC:
703 error_named("System constant not implemented in Z-code",
704 system_constants.keywords[t]);
709 /* Must match the switch statement below */
710 int glulx_system_constant_list[] =
712 identifiers_table_SC,
713 array_names_offset_SC,
717 dynam_string_table_SC,
721 highest_class_number_SC,
722 highest_object_number_SC,
725 static int32 value_of_system_constant_g(int t)
728 case classes_table_SC:
729 return Write_RAM_At + class_numbers_offset;
730 case identifiers_table_SC:
731 return Write_RAM_At + identifier_names_offset;
732 case array_names_offset_SC:
733 return Write_RAM_At + array_names_offset;
735 return prop_defaults_offset;
737 return Write_RAM_At + class_numbers_offset;
738 case dictionary_table_SC:
739 return dictionary_offset;
740 case dynam_string_table_SC:
741 return abbreviations_offset;
742 case grammar_table_SC:
743 return grammar_table_offset;
744 case actions_table_SC:
745 return actions_offset;
746 case globals_array_SC:
747 return variables_offset;
748 case highest_class_number_SC:
750 case highest_object_number_SC:
754 error_named("System constant not implemented in Glulx",
755 system_constants.keywords[t]);
760 extern int32 value_of_system_constant(int t)
763 return value_of_system_constant_z(t);
765 return value_of_system_constant_g(t);
768 static int evaluate_term(token_data t, assembly_operand *o)
770 /* If the given token is a constant, evaluate it into the operand.
771 For now, the identifiers are considered variables.
773 Returns FALSE if it fails to understand type. */
777 o->marker = t.marker;
778 o->symtype = t.symtype;
779 o->symflags = t.symflags;
782 { case LARGE_NUMBER_TT:
785 if (v < 0) v = v + 0x10000;
786 o->type = LONG_CONSTANT_OT;
791 o->type = CONSTANT_OT;
794 case SMALL_NUMBER_TT:
797 if (v < 0) v = v + 0x10000;
798 o->type = SHORT_CONSTANT_OT;
807 /* Find the dictionary address, adding to dictionary if absent */
809 o->type = LONG_CONSTANT_OT;
811 o->type = CONSTANT_OT;
812 o->value = dictionary_add(t.text, 0x80, 0, 0);
815 /* Create as a static string */
817 o->type = LONG_CONSTANT_OT;
819 o->type = CONSTANT_OT;
820 o->value = compile_string(t.text, FALSE, FALSE);
824 o->type = VARIABLE_OT;
827 if (t.value >= MAX_LOCAL_VARIABLES) {
828 o->type = GLOBALVAR_OT;
831 /* This includes "local variable zero", which is really
832 the stack-pointer magic variable. */
833 o->type = LOCALVAR_OT;
840 o->type = VARIABLE_OT;
841 o->value = t.value + 256;
847 system_function_usage[t.value] = 1;
850 *o = action_of_name(t.text);
852 case SYSTEM_CONSTANT_TT:
853 /* Certain system constants depend only on the
854 version number and need no backpatching, as they
855 are known in advance. We can therefore evaluate
858 o->type = LONG_CONSTANT_OT;
861 case version_number_SC:
862 o->type = SHORT_CONSTANT_OT;
864 v = version_number; break;
866 o->type = SHORT_CONSTANT_OT;
868 v = (version_number==3)?4:6; break;
870 o->type = SHORT_CONSTANT_OT;
872 v = (version_number==3)?5:7; break;
874 o->type = SHORT_CONSTANT_OT;
876 v = (version_number==3)?6:8; break;
877 case lowest_attribute_number_SC:
878 case lowest_action_number_SC:
879 case lowest_routine_number_SC:
880 case lowest_array_number_SC:
881 case lowest_constant_number_SC:
882 case lowest_class_number_SC:
883 o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 0; break;
884 case lowest_object_number_SC:
885 case lowest_property_number_SC:
886 o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 1; break;
887 case lowest_global_number_SC:
888 o->type = SHORT_CONSTANT_OT; o->marker = 0; v = 16; break;
889 case lowest_fake_action_number_SC:
890 o->type = LONG_CONSTANT_OT; o->marker = 0;
891 v = ((grammar_version_number==1)?256:4096); break;
892 case oddeven_packing_SC:
893 o->type = SHORT_CONSTANT_OT; o->marker = 0;
894 v = oddeven_packing_switch; break;
897 o->marker = INCON_MV;
903 o->type = CONSTANT_OT;
906 /* The three dict_par flags point at the lower byte
907 of the flag field, because the library is written
908 to expect one-byte fields, even though the compiler
909 generates a dictionary with room for two. */
911 o->type = BYTECONSTANT_OT;
913 v = DICT_ENTRY_FLAG_POS+1;
916 o->type = BYTECONSTANT_OT;
918 v = DICT_ENTRY_FLAG_POS+3;
921 o->type = BYTECONSTANT_OT;
923 v = DICT_ENTRY_FLAG_POS+5;
926 case lowest_attribute_number_SC:
927 case lowest_action_number_SC:
928 case lowest_routine_number_SC:
929 case lowest_array_number_SC:
930 case lowest_constant_number_SC:
931 case lowest_class_number_SC:
932 o->type = BYTECONSTANT_OT;
936 case lowest_object_number_SC:
937 case lowest_property_number_SC:
938 o->type = BYTECONSTANT_OT;
943 /* ###fix: need to fill more of these in! */
947 o->marker = INCON_MV;
958 /* --- Emitter ------------------------------------------------------------- */
960 expression_tree_node *ET;
963 extern void clear_expression_space(void)
967 static assembly_operand *emitter_stack;
968 static int *emitter_markers;
969 static int *emitter_bracket_counts;
971 #define FUNCTION_VALUE_MARKER 1
972 #define ARGUMENT_VALUE_MARKER 2
973 #define OR_VALUE_MARKER 3
975 static int emitter_sp;
977 static int is_property_t(int symbol_type)
978 { return ((symbol_type == PROPERTY_T) || (symbol_type == INDIVIDUAL_PROPERTY_T));
981 static void mark_top_of_emitter_stack(int marker, token_data t)
982 { if (emitter_sp < 1)
983 { compiler_error("SR error: Attempt to add a marker to the top of an empty emitter stack");
986 if (expr_trace_level >= 2)
987 { printf("Marking top of emitter stack (which is ");
988 print_operand(emitter_stack[emitter_sp-1]);
992 case FUNCTION_VALUE_MARKER:
995 case ARGUMENT_VALUE_MARKER:
998 case OR_VALUE_MARKER:
1007 if (emitter_markers[emitter_sp-1])
1008 { if (marker == ARGUMENT_VALUE_MARKER)
1010 warning("Ignoring spurious leading comma");
1013 error_named("Missing operand for", t.text);
1014 if (emitter_sp == MAX_EXPRESSION_NODES)
1015 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1016 emitter_markers[emitter_sp] = 0;
1017 emitter_bracket_counts[emitter_sp] = 0;
1018 emitter_stack[emitter_sp] = zero_operand;
1021 emitter_markers[emitter_sp-1] = marker;
1024 static void add_bracket_layer_to_emitter_stack(int depth)
1025 { /* There's no point in tracking bracket layers that don't fence off any values. */
1026 if (emitter_sp < depth + 1) return;
1027 if (expr_trace_level >= 2)
1028 printf("Adding bracket layer\n");
1029 ++emitter_bracket_counts[emitter_sp-depth-1];
1032 static void remove_bracket_layer_from_emitter_stack()
1033 { /* Bracket layers that don't fence off any values will not have been tracked. */
1034 if (emitter_sp < 2) return;
1035 if (expr_trace_level >= 2)
1036 printf("Removing bracket layer\n");
1037 if (emitter_bracket_counts[emitter_sp-2] <= 0)
1038 { compiler_error("SR error: Attempt to remove a nonexistent bracket layer from the emitter stack");
1041 --emitter_bracket_counts[emitter_sp-2];
1044 static void emit_token(token_data t)
1045 { assembly_operand o1, o2; int arity, stack_size, i;
1046 int op_node_number, operand_node_number, previous_node_number;
1049 if (expr_trace_level >= 2)
1050 { printf("Output: %-19s%21s ", t.text, "");
1051 for (i=0; i<emitter_sp; i++)
1052 { print_operand(emitter_stack[i]); printf(" ");
1053 if (emitter_markers[i] == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
1054 if (emitter_markers[i] == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
1055 if (emitter_markers[i] == OR_VALUE_MARKER) printf(":OR ");
1056 if (emitter_bracket_counts[i]) printf(":BRACKETS(%d) ", emitter_bracket_counts[i]);
1061 if (t.type == SUBOPEN_TT) return;
1064 while ((stack_size < emitter_sp) &&
1065 !emitter_markers[emitter_sp-stack_size-1] &&
1066 !emitter_bracket_counts[emitter_sp-stack_size-1])
1069 if (t.type == SUBCLOSE_TT)
1070 { if (stack_size < emitter_sp && emitter_bracket_counts[emitter_sp-stack_size-1])
1071 { if (stack_size == 0)
1072 { error("No expression between brackets '(' and ')'");
1073 emitter_stack[emitter_sp] = zero_operand;
1074 emitter_markers[emitter_sp] = 0;
1075 emitter_bracket_counts[emitter_sp] = 0;
1078 else if (stack_size < 1)
1079 compiler_error("SR error: emitter stack empty in subexpression");
1080 else if (stack_size > 1)
1081 compiler_error("SR error: emitter stack overfull in subexpression");
1082 remove_bracket_layer_from_emitter_stack();
1087 if (t.type != OP_TT)
1088 { emitter_markers[emitter_sp] = 0;
1089 emitter_bracket_counts[emitter_sp] = 0;
1091 if (emitter_sp == MAX_EXPRESSION_NODES)
1092 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1093 if (!evaluate_term(t, &(emitter_stack[emitter_sp++])))
1094 compiler_error_named("Emit token error:", t.text);
1098 /* A comma is argument-separating if it follows an argument (or a function
1099 call, since we ignore spurious leading commas in function argument lists)
1100 with no intervening brackets. Function calls are variadic, so we don't
1101 apply argument-separating commas. */
1102 if (t.value == COMMA_OP &&
1103 stack_size < emitter_sp &&
1104 (emitter_markers[emitter_sp-stack_size-1] == ARGUMENT_VALUE_MARKER ||
1105 emitter_markers[emitter_sp-stack_size-1] == FUNCTION_VALUE_MARKER) &&
1106 !emitter_bracket_counts[emitter_sp-stack_size-1])
1107 { if (expr_trace_level >= 2)
1108 printf("Treating comma as argument-separating\n");
1112 if (t.value == OR_OP)
1116 if (t.value == FCALL_OP)
1117 { if (expr_trace_level >= 3)
1118 { printf("FCALL_OP finds marker stack: ");
1119 for (x=0; x<emitter_sp; x++) printf("%d ", emitter_markers[x]);
1122 if (emitter_markers[emitter_sp-1] == ARGUMENT_VALUE_MARKER)
1123 warning("Ignoring spurious trailing comma");
1124 while (emitter_markers[emitter_sp-arity] != FUNCTION_VALUE_MARKER)
1127 emitter_stack[emitter_sp-arity].type == SYSFUN_OT) ||
1129 emitter_stack[emitter_sp-arity].type == VARIABLE_OT &&
1130 emitter_stack[emitter_sp-arity].value >= 256 &&
1131 emitter_stack[emitter_sp-arity].value < 288))
1132 { int index = emitter_stack[emitter_sp-arity].value;
1135 if(index >= 0 && index < NUMBER_SYSTEM_FUNCTIONS)
1136 error_named("System function name used as a value:", system_functions.keywords[index]);
1138 compiler_error("Found unnamed system function used as a value");
1139 emitter_stack[emitter_sp-arity] = zero_operand;
1146 if (operators[t.value].usage == IN_U) arity = 2;
1148 if (operators[t.value].precedence == 3)
1151 if(!emitter_markers[x] && !emitter_bracket_counts[x])
1152 { for (--x; emitter_markers[x] == OR_VALUE_MARKER && !emitter_bracket_counts[x]; --x)
1156 for (;x >= 0 && !emitter_markers[x] && !emitter_bracket_counts[x]; --x)
1161 if (arity > stack_size)
1162 { error_named("Missing operand for", t.text);
1163 while (arity > stack_size)
1164 { if (emitter_sp == MAX_EXPRESSION_NODES)
1165 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1166 emitter_markers[emitter_sp] = 0;
1167 emitter_bracket_counts[emitter_sp] = 0;
1168 emitter_stack[emitter_sp] = zero_operand;
1175 /* pseudo-typecheck in 6.30 */
1176 for (i = 1; i <= arity; i++)
1178 o1 = emitter_stack[emitter_sp - i];
1179 if (is_property_t(o1.symtype) ) {
1183 case SETEQUALS_OP: case NOTEQUAL_OP:
1185 case PROVIDES_OP: case NOTPROVIDES_OP:
1186 case PROP_ADD_OP: case PROP_NUM_OP:
1188 case MPROP_ADD_OP: case MESSAGE_OP:
1190 if (i < arity) break;
1191 case GE_OP: case LE_OP:
1192 if ((i < arity) && (o1.symflags & STAR_SFLAG)) break;
1194 warning("Property name in expression is not qualified by object");
1196 } /* if (is_property_t */
1201 o1 = emitter_stack[emitter_sp - 1];
1202 if ((o1.marker == 0) && is_constant_ot(o1.type))
1204 { case UNARY_MINUS_OP: x = -o1.value; goto FoldConstant;
1207 x = (~o1.value) & 0xffff;
1209 x = (~o1.value) & 0xffffffff;
1212 if (o1.value != 0) x=0; else x=1;
1219 o1 = emitter_stack[emitter_sp - 2];
1220 o2 = emitter_stack[emitter_sp - 1];
1222 if ((o1.marker == 0) && (o2.marker == 0)
1223 && is_constant_ot(o1.type) && is_constant_ot(o2.type))
1231 { ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value;
1232 ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
1237 case PLUS_OP: x = ov1 + ov2; goto FoldConstantC;
1238 case MINUS_OP: x = ov1 - ov2; goto FoldConstantC;
1239 case TIMES_OP: x = ov1 * ov2; goto FoldConstantC;
1243 error("Division of constant by zero");
1245 if (t.value == DIVIDE_OP) {
1253 x = -((-ov1) / ov2);
1262 x = -((-ov1) % ov2);
1265 case ARTAND_OP: x = o1.value & o2.value; goto FoldConstant;
1266 case ARTOR_OP: x = o1.value | o2.value; goto FoldConstant;
1268 if (o1.value == o2.value) x = 1; else x = 0;
1271 if (o1.value != o2.value) x = 1; else x = 0;
1274 if (o1.value >= o2.value) x = 1; else x = 0;
1277 if (o1.value > o2.value) x = 1; else x = 0;
1280 if (o1.value <= o2.value) x = 1; else x = 0;
1283 if (o1.value < o2.value) x = 1; else x = 0;
1286 if ((o1.value != 0) && (o2.value != 0)) x=1; else x=0;
1289 if ((o1.value != 0) || (o2.value != 0)) x=1; else x=0;
1296 op_node_number = ET_used++;
1297 if (op_node_number == MAX_EXPRESSION_NODES)
1298 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1300 ET[op_node_number].operator_number = t.value;
1301 ET[op_node_number].up = -1;
1302 ET[op_node_number].down = -1;
1303 ET[op_node_number].right = -1;
1305 /* This statement is redundant, but prevents compilers from wrongly
1306 issuing a "used before it was assigned a value" error: */
1307 previous_node_number = 0;
1309 for (i = emitter_sp-arity; i != emitter_sp; i++)
1311 if (expr_trace_level >= 3)
1312 printf("i=%d, emitter_sp=%d, arity=%d, ETU=%d\n",
1313 i, emitter_sp, arity, ET_used);
1314 if (emitter_stack[i].type == EXPRESSION_OT)
1315 operand_node_number = emitter_stack[i].value;
1317 { operand_node_number = ET_used++;
1318 if (operand_node_number == MAX_EXPRESSION_NODES)
1319 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1320 ET[operand_node_number].down = -1;
1321 ET[operand_node_number].value = emitter_stack[i];
1323 ET[operand_node_number].up = op_node_number;
1324 ET[operand_node_number].right = -1;
1325 if (i == emitter_sp - arity)
1326 { ET[op_node_number].down = operand_node_number;
1329 { ET[previous_node_number].right = operand_node_number;
1331 previous_node_number = operand_node_number;
1334 emitter_sp = emitter_sp - arity + 1;
1336 emitter_stack[emitter_sp - 1].type = EXPRESSION_OT;
1337 emitter_stack[emitter_sp - 1].value = op_node_number;
1338 emitter_stack[emitter_sp - 1].marker = 0;
1339 emitter_markers[emitter_sp - 1] = 0;
1340 emitter_bracket_counts[emitter_sp - 1] = 0;
1341 /* Remove the marker for the brackets implied by operator precedence */
1342 remove_bracket_layer_from_emitter_stack();
1348 /* In Glulx, skip this test; we can't check out-of-range errors
1349 for 32-bit arithmetic. */
1351 if (!glulx_mode && ((x<-32768) || (x > 32767)))
1352 { char folding_error[40];
1353 int32 ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value;
1354 int32 ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
1358 sprintf(folding_error, "%d + %d = %d", ov1, ov2, x);
1361 sprintf(folding_error, "%d - %d = %d", ov1, ov2, x);
1364 sprintf(folding_error, "%d * %d = %d", ov1, ov2, x);
1367 error_named("Signed arithmetic on compile-time constants overflowed \
1368 the range -32768 to +32767:", folding_error);
1374 while (x < 0) x = x + 0x10000;
1381 emitter_sp = emitter_sp - arity + 1;
1385 emitter_stack[emitter_sp - 1].type = SHORT_CONSTANT_OT;
1386 else emitter_stack[emitter_sp - 1].type = LONG_CONSTANT_OT;
1390 emitter_stack[emitter_sp - 1].type = ZEROCONSTANT_OT;
1391 else if (x >= -128 && x <= 127)
1392 emitter_stack[emitter_sp - 1].type = BYTECONSTANT_OT;
1393 else if (x >= -32768 && x <= 32767)
1394 emitter_stack[emitter_sp - 1].type = HALFCONSTANT_OT;
1396 emitter_stack[emitter_sp - 1].type = CONSTANT_OT;
1399 emitter_stack[emitter_sp - 1].value = x;
1400 emitter_stack[emitter_sp - 1].marker = 0;
1401 emitter_markers[emitter_sp - 1] = 0;
1402 emitter_bracket_counts[emitter_sp - 1] = 0;
1404 if (expr_trace_level >= 2)
1405 { printf("Folding constant to: ");
1406 print_operand(emitter_stack[emitter_sp - 1]);
1410 /* Remove the marker for the brackets implied by operator precedence */
1411 remove_bracket_layer_from_emitter_stack();
1415 /* --- Pretty printing ----------------------------------------------------- */
1417 static void show_node(int n, int depth, int annotate)
1419 for (j=0; j<2*depth+2; j++) printf(" ");
1421 if (ET[n].down == -1)
1422 { print_operand(ET[n].value);
1423 if (annotate && (ET[n].value.marker != 0))
1424 printf(" [%s]", describe_mv(ET[n].value.marker));
1428 { printf("%s ", operators[ET[n].operator_number].description);
1429 j = operators[ET[n].operator_number].precedence;
1430 if ((annotate) && ((j==2) || (j==3)))
1431 { printf(" %d|%d ", ET[n].true_label, ET[n].false_label);
1432 if (ET[n].label_after != -1) printf(" def %d after ",
1434 if (ET[n].to_expression) printf(" con to expr ");
1437 show_node(ET[n].down, depth+1, annotate);
1440 if (ET[n].right != -1) show_node(ET[n].right, depth, annotate);
1443 extern void show_tree(assembly_operand AO, int annotate)
1444 { if (AO.type == EXPRESSION_OT) show_node(AO.value, 0, annotate);
1446 { printf("Constant: "); print_operand(AO);
1447 if (annotate && (AO.marker != 0))
1448 printf(" [%s]", describe_mv(AO.marker));
1453 /* --- Lvalue transformations ---------------------------------------------- */
1455 /* This only gets called in Z-code, since Glulx doesn't distinguish
1456 individual property operators from general ones. */
1457 static void check_property_operator(int from_node)
1458 { int below = ET[from_node].down;
1459 int opnum = ET[from_node].operator_number;
1463 if (veneer_mode) return;
1465 if ((below != -1) && (ET[below].right != -1))
1466 { int n = ET[below].right, flag = FALSE;
1468 if ((ET[n].down == -1)
1469 && ((ET[n].value.type == LONG_CONSTANT_OT)
1470 || (ET[n].value.type == SHORT_CONSTANT_OT))
1471 && ((ET[n].value.value > 0) && (ET[n].value.value < 64))
1472 && ((!module_switch) || (ET[n].value.marker == 0)))
1477 { case PROPERTY_OP: opnum = MESSAGE_OP; break;
1478 case PROP_ADD_OP: opnum = MPROP_ADD_OP; break;
1479 case PROP_NUM_OP: opnum = MPROP_NUM_OP; break;
1483 ET[from_node].operator_number = opnum;
1487 check_property_operator(below);
1488 if (ET[from_node].right != -1)
1489 check_property_operator(ET[from_node].right);
1492 static void check_lvalues(int from_node)
1493 { int below = ET[from_node].down;
1494 int opnum = ET[from_node].operator_number, opnum_below;
1495 int lvalue_form, i, j = 0;
1499 if ((opnum == FCALL_OP) && (ET[below].down != -1))
1500 { opnum_below = ET[below].operator_number;
1501 if ((opnum_below == PROPERTY_OP) || (opnum_below == MESSAGE_OP))
1502 { i = ET[ET[from_node].down].right;
1503 ET[from_node].down = ET[below].down;
1504 ET[ET[below].down].up = from_node;
1505 ET[ET[ET[below].down].right].up = from_node;
1506 ET[ET[ET[below].down].right].right = i;
1507 opnum = PROP_CALL_OP;
1508 ET[from_node].operator_number = opnum;
1512 if (operators[opnum].requires_lvalue)
1513 { opnum_below = ET[below].operator_number;
1515 if (ET[below].down == -1)
1516 { if (!is_variable_ot(ET[below].value.type))
1517 { error("'=' applied to undeclared variable");
1524 { case SETEQUALS_OP:
1526 { case ARROW_OP: lvalue_form = ARROW_SETEQUALS_OP; break;
1527 case DARROW_OP: lvalue_form = DARROW_SETEQUALS_OP; break;
1528 case MESSAGE_OP: lvalue_form = MESSAGE_SETEQUALS_OP; break;
1529 case PROPERTY_OP: lvalue_form = PROPERTY_SETEQUALS_OP; break;
1534 { case ARROW_OP: lvalue_form = ARROW_INC_OP; break;
1535 case DARROW_OP: lvalue_form = DARROW_INC_OP; break;
1536 case MESSAGE_OP: lvalue_form = MESSAGE_INC_OP; break;
1537 case PROPERTY_OP: lvalue_form = PROPERTY_INC_OP; break;
1542 { case ARROW_OP: lvalue_form = ARROW_POST_INC_OP; break;
1543 case DARROW_OP: lvalue_form = DARROW_POST_INC_OP; break;
1544 case MESSAGE_OP: lvalue_form = MESSAGE_POST_INC_OP; break;
1545 case PROPERTY_OP: lvalue_form = PROPERTY_POST_INC_OP; break;
1550 { case ARROW_OP: lvalue_form = ARROW_DEC_OP; break;
1551 case DARROW_OP: lvalue_form = DARROW_DEC_OP; break;
1552 case MESSAGE_OP: lvalue_form = MESSAGE_DEC_OP; break;
1553 case PROPERTY_OP: lvalue_form = PROPERTY_DEC_OP; break;
1558 { case ARROW_OP: lvalue_form = ARROW_POST_DEC_OP; break;
1559 case DARROW_OP: lvalue_form = DARROW_POST_DEC_OP; break;
1560 case MESSAGE_OP: lvalue_form = MESSAGE_POST_DEC_OP; break;
1561 case PROPERTY_OP: lvalue_form = PROPERTY_POST_DEC_OP; break;
1565 if (lvalue_form == 0)
1566 { error_named("'=' applied to",
1567 (char *) operators[opnum_below].description);
1571 /* Transform from_node from_node
1573 below value to value
1577 ET[from_node].operator_number = lvalue_form;
1579 ET[from_node].down = i;
1581 { ET[i].up = from_node;
1585 ET[j].right = ET[below].right;
1588 check_lvalues(below);
1590 if (ET[from_node].right != -1)
1591 check_lvalues(ET[from_node].right);
1595 ET[from_node].down = -1;
1596 ET[from_node].value = zero_operand;
1597 if (ET[from_node].right != -1)
1598 check_lvalues(ET[from_node].right);
1601 /* --- Tree surgery for conditionals --------------------------------------- */
1603 static void negate_condition(int n)
1606 if (ET[n].right != -1) negate_condition(ET[n].right);
1607 if (ET[n].down == -1) return;
1608 i = operators[ET[n].operator_number].negation;
1609 if (i!=0) ET[n].operator_number = i;
1610 if (operators[i].precedence==2) negate_condition(ET[n].down);
1613 static void delete_negations(int n, int context)
1615 /* Recursively apply
1617 ~~(x && y) = ~~x || ~~y
1618 ~~(x || y) = ~~x && ~~y
1621 (etc) to delete the ~~ operator from the tree. Since this is
1622 depth first, the ~~ being deleted has no ~~s beneath it, which
1623 is important to make "negate_condition" work. */
1627 if (ET[n].right != -1) delete_negations(ET[n].right, context);
1628 if (ET[n].down == -1) return;
1629 delete_negations(ET[n].down, context);
1631 if (ET[n].operator_number == LOGNOT_OP)
1632 { negate_condition(ET[n].down);
1633 ET[n].operator_number
1634 = ET[ET[n].down].operator_number;
1635 ET[n].down = ET[ET[n].down].down;
1637 while(i != -1) { ET[i].up = n; i = ET[i].right; }
1641 static void insert_exp_to_cond(int n, int context)
1643 /* Insert a ~= test when an expression is used as a condition.
1645 Check for possible confusion over = and ==, e.g. "if (a = 1) ..." */
1649 if (ET[n].right != -1) insert_exp_to_cond(ET[n].right, context);
1651 if (ET[n].down == -1)
1652 { if (context==CONDITION_CONTEXT)
1654 if (new == MAX_EXPRESSION_NODES)
1655 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1657 ET[n].down = new; ET[n].operator_number = NONZERO_OP;
1658 ET[new].up = n; ET[new].right = -1;
1663 switch(operators[ET[n].operator_number].precedence)
1664 { case 3: /* Conditionals have level 3 */
1665 context = QUANTITY_CONTEXT;
1667 case 2: /* Logical operators level 2 */
1668 context = CONDITION_CONTEXT;
1670 case 1: /* Forms of '=' have level 1 */
1671 if (context == CONDITION_CONTEXT)
1672 warning("'=' used as condition: '==' intended?");
1674 if (context != CONDITION_CONTEXT) break;
1677 if (new == MAX_EXPRESSION_NODES)
1678 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1680 ET[n].down = new; ET[n].operator_number = NONZERO_OP;
1681 ET[new].up = n; ET[new].right = -1;
1684 while (i!= -1) { ET[i].up = new; i = ET[i].right; }
1685 context = QUANTITY_CONTEXT; n = new;
1688 insert_exp_to_cond(ET[n].down, context);
1691 static unsigned int etoken_num_children(int n)
1696 if (i == -1) { return 0; }
1704 static void func_args_on_stack(int n, int context)
1706 /* Make sure that the arguments of every function-call expression
1707 are stored to the stack. If any aren't (ie, if any arguments are
1708 constants or variables), cover them with push operators.
1709 (The very first argument does not need to be so treated, because
1710 it's the function address, not a function argument. We also
1711 skip the treatment for most system functions.) */
1713 int new, pn, fnaddr, opnum;
1717 if (ET[n].right != -1)
1718 func_args_on_stack(ET[n].right, context);
1719 if (ET[n].down == -1) {
1722 opnum = ET[pn].operator_number;
1723 if (opnum == FCALL_OP
1724 || opnum == MESSAGE_CALL_OP
1725 || opnum == PROP_CALL_OP) {
1726 /* If it's an FCALL, get the operand which contains the function
1727 address (or system-function number) */
1728 if (opnum == MESSAGE_CALL_OP
1729 || opnum == PROP_CALL_OP
1730 || ((fnaddr=ET[pn].down) != n
1731 && (ET[fnaddr].value.type != SYSFUN_OT
1732 || ET[fnaddr].value.value == INDIRECT_SYSF
1733 || ET[fnaddr].value.value == GLK_SYSF))) {
1734 if (etoken_num_children(pn) > (unsigned int)(opnum == FCALL_OP ? 4:3)) {
1736 if (new == MAX_EXPRESSION_NODES)
1737 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1740 ET[n].operator_number = PUSH_OP;
1750 func_args_on_stack(ET[n].down, context);
1753 static assembly_operand check_conditions(assembly_operand AO, int context)
1756 if (AO.type != EXPRESSION_OT)
1757 { if (context != CONDITION_CONTEXT) return AO;
1759 if (n == MAX_EXPRESSION_NODES)
1760 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1765 INITAOT(&AO, EXPRESSION_OT);
1769 insert_exp_to_cond(AO.value, context);
1770 delete_negations(AO.value, context);
1773 func_args_on_stack(AO.value, context);
1778 /* --- Shift-reduce parser ------------------------------------------------- */
1781 static token_data *sr_stack;
1783 extern assembly_operand parse_expression(int context)
1785 /* Parses an expression, evaluating it as a constant if possible.
1787 Possible contexts are:
1789 VOID_CONTEXT the expression is used as a statement, so that
1790 its value will be thrown away and it only
1791 needs to exist for any resulting side-effects
1792 (function calls and assignments)
1794 CONDITION_CONTEXT the result must be a condition
1796 CONSTANT_CONTEXT there is required to be a constant result
1797 (so that, for instance, comma becomes illegal)
1799 QUANTITY_CONTEXT the default: a quantity is to be specified
1801 ACTION_Q_CONTEXT like QUANTITY_CONTEXT, but postfixed brackets
1802 at the top level do not indicate function call:
1804 <Insert button (random(pocket1, pocket2))>
1806 RETURN_Q_CONTEXT like QUANTITY_CONTEXT, but a single property
1807 name does not generate a warning
1809 ASSEMBLY_CONTEXT a quantity which cannot use the '->' operator
1810 (needed for assembly language to indicate
1813 FORINIT_CONTEXT a quantity which cannot use an (unbracketed)
1816 ARRAY_CONTEXT like CONSTANT_CONTEXT, but where an unbracketed
1817 minus sign is ambiguous, and brackets always
1818 indicate subexpressions, not function calls
1820 Return value: an assembly operand.
1822 If the type is OMITTED_OT, then the expression has no resulting value.
1824 If the type is EXPRESSION_OT, then the value will need to be
1825 calculated at run-time by code compiled from the expression tree
1826 whose root node-number is the operand value.
1828 Otherwise the assembly operand is the value of the expression, which
1829 is constant and thus known at compile time.
1831 If an error has occurred in the expression, which recovery from was
1832 not possible, then the return is (short constant) 0. This should
1833 minimise the chance of a cascade of further error messages.
1836 token_data a, b, pop; int i;
1837 assembly_operand AO;
1839 superclass_allowed = (context != FORINIT_CONTEXT);
1840 if (context == FORINIT_CONTEXT) context = VOID_CONTEXT;
1842 comma_allowed = (context == VOID_CONTEXT);
1843 arrow_allowed = (context != ASSEMBLY_CONTEXT);
1844 bare_prop_allowed = (context == RETURN_Q_CONTEXT);
1845 array_init_ambiguity = ((context == ARRAY_CONTEXT) ||
1846 (context == ASSEMBLY_CONTEXT));
1848 action_ambiguity = (context == ACTION_Q_CONTEXT);
1850 if (context == ASSEMBLY_CONTEXT) context = QUANTITY_CONTEXT;
1851 if (context == ACTION_Q_CONTEXT) context = QUANTITY_CONTEXT;
1852 if (context == RETURN_Q_CONTEXT) context = QUANTITY_CONTEXT;
1853 if (context == ARRAY_CONTEXT) context = CONSTANT_CONTEXT;
1856 inserting_token = FALSE;
1861 previous_token.text = "$";
1862 previous_token.type = ENDEXP_TT;
1863 previous_token.value = 0;
1866 sr_stack[0] = previous_token;
1870 statements.enabled = FALSE;
1871 directives.enabled = FALSE;
1873 if (get_next_etoken() == FALSE)
1874 { ebf_error("expression", token_text);
1879 { if (expr_trace_level >= 2)
1880 { printf("Input: %-20s", current_token.text);
1881 for (i=0; i<sr_sp; i++) printf("%s ", sr_stack[i].text);
1884 if (expr_trace_level >= 3) printf("ET_used = %d\n", ET_used);
1887 { compiler_error("SR error: stack empty");
1891 a = sr_stack[sr_sp-1]; b = current_token;
1893 if ((a.type == ENDEXP_TT) && (b.type == ENDEXP_TT))
1894 { if (emitter_sp == 0)
1895 { error("No expression between brackets '(' and ')'");
1900 { compiler_error("SR error: emitter stack overfull");
1904 AO = emitter_stack[0];
1905 if (AO.type == EXPRESSION_OT)
1906 { if (expr_trace_level >= 3)
1907 { printf("Tree before lvalue checking:\n");
1908 show_tree(AO, FALSE);
1911 check_property_operator(AO.value);
1912 check_lvalues(AO.value);
1913 ET[AO.value].up = -1;
1916 if ((context != CONSTANT_CONTEXT) && is_property_t(AO.symtype)
1917 && (arrow_allowed) && (!bare_prop_allowed))
1918 warning("Bare property name found. \"self.prop\" intended?");
1921 check_conditions(AO, context);
1923 if (context == CONSTANT_CONTEXT)
1924 if (!is_constant_ot(AO.type))
1925 { AO = zero_operand;
1926 ebf_error("constant", "<expression>");
1933 switch(find_prec(a,b))
1935 case e5: /* Associativity error */
1936 error_named("Brackets mandatory to clarify order of:",
1941 if (sr_sp == MAX_EXPRESSION_NODES)
1942 memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
1943 sr_stack[sr_sp++] = b;
1947 if (sr_sp >= 2 && sr_stack[sr_sp-2].type == OP_TT && sr_stack[sr_sp-2].value == FCALL_OP)
1948 mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, b);
1950 add_bracket_layer_to_emitter_stack(0);
1955 if (sr_stack[sr_sp-2].type == OP_TT &&
1956 operators[sr_stack[sr_sp-2].value].precedence == 3)
1957 mark_top_of_emitter_stack(OR_VALUE_MARKER, b);
1959 { error("'or' not between values to the right of a condition");
1960 /* Convert to + for error recovery purposes */
1961 sr_stack[sr_sp-1].value = PLUS_OP;
1966 /* A comma separates arguments only if the shallowest open bracket belongs to a function call. */
1967 int shallowest_open_bracket_index = sr_sp - 2;
1968 while (shallowest_open_bracket_index > 0 && sr_stack[shallowest_open_bracket_index].type != SUBOPEN_TT)
1969 --shallowest_open_bracket_index;
1970 if (shallowest_open_bracket_index > 0 &&
1971 sr_stack[shallowest_open_bracket_index-1].type == OP_TT &&
1972 sr_stack[shallowest_open_bracket_index-1].value == FCALL_OP)
1973 { mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, b);
1976 /* Non-argument-separating commas get treated like any other operator; we fall through to the default case. */
1980 /* Add a marker for the brackets implied by operator precedence */
1981 int operands_on_left = (operators[b.value].usage == PRE_U) ? 0 : 1;
1982 add_bracket_layer_to_emitter_stack(operands_on_left);
1990 { pop = sr_stack[sr_sp - 1];
1993 } while (find_prec(sr_stack[sr_sp-1], pop) != LOWER_P);
1996 case e1: /* Missing operand error */
1997 error_named("Missing operand after", a.text);
1999 current_token.type = NUMBER_TT;
2000 current_token.value = 0;
2001 current_token.marker = 0;
2002 current_token.text = "0";
2005 case e2: /* Unexpected close bracket */
2006 error("Found '(' without matching ')'");
2010 case e3: /* Missing operator error */
2011 error("Missing operator: inserting '+'");
2013 current_token.type = OP_TT;
2014 current_token.value = PLUS_OP;
2015 current_token.marker = 0;
2016 current_token.text = "+";
2019 case e4: /* Expression ends with an open bracket */
2020 error("Found '(' without matching ')'");
2029 /* --- Test for simple ++ or -- usage: used to optimise "for" loop code ---- */
2031 extern int test_for_incdec(assembly_operand AO)
2033 if (AO.type != EXPRESSION_OT) return 0;
2034 if (ET[AO.value].down == -1) return 0;
2035 switch(ET[AO.value].operator_number)
2036 { case INC_OP: s = 1; break;
2037 case POST_INC_OP: s = 1; break;
2038 case DEC_OP: s = -1; break;
2039 case POST_DEC_OP: s = -1; break;
2042 if (ET[ET[AO.value].down].down != -1) return 0;
2043 if (!is_variable_ot(ET[ET[AO.value].down].value.type)) return 0;
2044 return s*(ET[ET[AO.value].down].value.value);
2047 /* ========================================================================= */
2048 /* Data structure management routines */
2049 /* ------------------------------------------------------------------------- */
2051 extern void init_expressp_vars(void)
2053 /* make_operands(); */
2054 make_lexical_interface_tables();
2055 for (i=0;i<32;i++) system_function_usage[i] = 0;
2058 extern void expressp_begin_pass(void)
2062 extern void expressp_allocate_arrays(void)
2063 { ET = my_calloc(sizeof(expression_tree_node), MAX_EXPRESSION_NODES,
2064 "expression parse trees");
2065 emitter_markers = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
2067 emitter_bracket_counts = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
2068 "emitter bracket layer counts");
2069 emitter_stack = my_calloc(sizeof(assembly_operand), MAX_EXPRESSION_NODES,
2071 sr_stack = my_calloc(sizeof(token_data), MAX_EXPRESSION_NODES,
2072 "shift-reduce parser stack");
2075 extern void expressp_free_arrays(void)
2076 { my_free(&ET, "expression parse trees");
2077 my_free(&emitter_markers, "emitter markers");
2078 my_free(&emitter_bracket_counts, "emitter bracket layer counts");
2079 my_free(&emitter_stack, "emitter stack");
2080 my_free(&sr_stack, "shift-reduce parser stack");
2083 /* ========================================================================= */