X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fexpressp.c;h=0e0cf6f2773002c9b501d693cba43d5b2832ef0e;hb=8e63120c630c94c598d4e2d6ba823dac59bce8fa;hp=5b3c0a714f99104d565625a5450fe06fe8ab0018;hpb=d11f2f726ed7feea617476d99cf7505ddd9a27ce;p=inform.git diff --git a/src/expressp.c b/src/expressp.c index 5b3c0a7..0e0cf6f 100644 --- a/src/expressp.c +++ b/src/expressp.c @@ -1,8 +1,8 @@ /* ------------------------------------------------------------------------- */ /* "expressp" : The expression parser */ /* */ -/* Part of Inform 6.35 */ -/* copyright (c) Graham Nelson 1993 - 2021 */ +/* Part of Inform 6.40 */ +/* copyright (c) Graham Nelson 1993 - 2022 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -65,10 +65,7 @@ static int comma_allowed, arrow_allowed, superclass_allowed, array_init_ambiguity, action_ambiguity, etoken_count, inserting_token, bracket_level; -extern int *variable_usage; - -/* Must be at least as many as keyword_group system_functions (currently 12) */ -int system_function_usage[32]; +int system_function_usage[NUMBER_SYSTEM_FUNCTIONS]; static int get_next_etoken(void) { int v, symbol = 0, mark_symbol_as_used = FALSE, @@ -86,6 +83,7 @@ static int get_next_etoken(void) current_token.value = token_value; current_token.type = token_type; current_token.marker = 0; + current_token.symindex = -1; current_token.symtype = 0; current_token.symflags = -1; } @@ -93,7 +91,7 @@ static int get_next_etoken(void) switch(current_token.type) { case LOCAL_VARIABLE_TT: current_token.type = VARIABLE_TT; - variable_usage[current_token.value] = TRUE; + variables[current_token.value].usage = TRUE; break; case DQ_TT: @@ -136,15 +134,16 @@ but not used as a value:", unicode); mark_symbol_as_used = TRUE; - v = svals[symbol]; + v = symbols[symbol].value; - current_token.symtype = stypes[symbol]; - current_token.symflags = sflags[symbol]; - switch(stypes[symbol]) + current_token.symindex = symbol; + current_token.symtype = symbols[symbol].type; + current_token.symflags = symbols[symbol].flags; + switch(symbols[symbol].type) { case ROUTINE_T: /* Replaced functions must always be backpatched because there could be another definition coming. */ - if (sflags[symbol] & REPLACE_SFLAG) + if (symbols[symbol].flags & REPLACE_SFLAG) { current_token.marker = SYMBOL_MV; if (module_switch) import_symbol(symbol); v = symbol; @@ -171,7 +170,7 @@ but not used as a value:", unicode); if (module_switch) current_token.marker = IDENT_MV; break; case CONSTANT_T: - if (sflags[symbol] & (UNKNOWN_SFLAG + CHANGE_SFLAG)) + if (symbols[symbol].flags & (UNKNOWN_SFLAG + CHANGE_SFLAG)) { current_token.marker = SYMBOL_MV; if (module_switch) import_symbol(symbol); v = symbol; @@ -185,7 +184,7 @@ but not used as a value:", unicode); current_token.marker = 0; break; } - if (sflags[symbol] & SYSTEM_SFLAG) + if (symbols[symbol].flags & SYSTEM_SFLAG) current_token.marker = 0; current_token.value = v; @@ -205,9 +204,9 @@ but not used as a value:", unicode); else current_token.type = SMALL_NUMBER_TT; } - if (stypes[symbol] == GLOBAL_VARIABLE_T) + if (symbols[symbol].type == GLOBAL_VARIABLE_T) { current_token.type = VARIABLE_TT; - variable_usage[current_token.value] = TRUE; + variables[current_token.value].usage = TRUE; } break; @@ -329,7 +328,7 @@ but not used as a value:", unicode); current_token.text += 3; current_token.type = SYMBOL_TT; symbol = symbol_index(current_token.text, -1); - if (stypes[symbol] != GLOBAL_VARIABLE_T) { + if (symbols[symbol].type != GLOBAL_VARIABLE_T) { ebf_error( "global variable name after '#g$'", current_token.text); @@ -339,7 +338,7 @@ but not used as a value:", unicode); break; } mark_symbol_as_used = TRUE; - current_token.value = svals[symbol] - MAX_LOCAL_VARIABLES; + current_token.value = symbols[symbol].value - MAX_LOCAL_VARIABLES; current_token.marker = 0; if (!glulx_mode) { if (current_token.value >= 0x100) @@ -439,7 +438,7 @@ but not used as a value:", unicode); if (token_type_allowable[current_token.type]==0) { if (expr_trace_level >= 3) { printf("Discarding as not allowable: '%s' ", current_token.text); - describe_token(current_token); + describe_token(¤t_token); printf("\n"); } current_token.type = ENDEXP_TT; @@ -454,16 +453,16 @@ but not used as a value:", unicode); || (operators[current_token.value].usage == PRE_U))) { if (expr_trace_level >= 3) { printf("Discarding as no longer part: '%s' ", current_token.text); - describe_token(current_token); + describe_token(¤t_token); printf("\n"); } current_token.type = ENDEXP_TT; } else - { if (mark_symbol_as_used) sflags[symbol] |= USED_SFLAG; + { if (mark_symbol_as_used) symbols[symbol].flags |= USED_SFLAG; if (expr_trace_level >= 3) { printf("Expr token = '%s' ", current_token.text); - describe_token(current_token); + describe_token(¤t_token); printf("\n"); } } @@ -500,7 +499,7 @@ const int prec_table[] = { }; -static int find_prec(token_data a, token_data b) +static int find_prec(const token_data *a, const token_data *b) { /* We are comparing the precedence of tokens a and b (where a occurs to the left of b). If the expression is correct, @@ -518,14 +517,14 @@ static int find_prec(token_data a, token_data b) int i, j, l1, l2; - switch(a.type) + switch(a->type) { case SUBOPEN_TT: i=0; break; case SUBCLOSE_TT: i=1; break; case ENDEXP_TT: i=2; break; case OP_TT: i=3; break; default: i=4; break; } - switch(b.type) + switch(b->type) { case SUBOPEN_TT: i+=0; break; case SUBCLOSE_TT: i+=5; break; case ENDEXP_TT: i+=10; break; @@ -535,10 +534,10 @@ static int find_prec(token_data a, token_data b) j = prec_table[i]; if (j != -1) return j; - l1 = operators[a.value].precedence; - l2 = operators[b.value].precedence; - if (operators[b.value].usage == PRE_U) return LOWER_P; - if (operators[a.value].usage == POST_U) return GREATER_P; + l1 = operators[a->value].precedence; + l2 = operators[b->value].precedence; + if (operators[b->value].usage == PRE_U) return LOWER_P; + if (operators[a->value].usage == POST_U) return GREATER_P; /* Anomalous rule to resolve the function call precedence, which is different on the right from on the left, e.g., in: @@ -551,7 +550,7 @@ static int find_prec(token_data a, token_data b) if (l1 < l2) return LOWER_P; if (l1 > l2) return GREATER_P; - switch(operators[a.value].associativity) + switch(operators[a->value].associativity) { case L_A: return GREATER_P; case R_A: return LOWER_P; case 0: return e5; @@ -561,7 +560,8 @@ static int find_prec(token_data a, token_data b) /* --- Converting token to operand ----------------------------------------- */ -/* Must match the switch statement below */ +/* List used to generate gameinfo.dbg. + Must match the switch statement below. */ int z_system_constant_list[] = { adjectives_table_SC, actions_table_SC, @@ -605,6 +605,8 @@ int z_system_constant_list[] = highest_class_number_SC, class_objects_array_SC, highest_object_number_SC, + dictionary_table_SC, + grammar_table_SC, -1 }; static int32 value_of_system_constant_z(int t) @@ -642,9 +644,13 @@ static int32 value_of_system_constant_z(int t) case ipv__end_SC: return variables_offset; case array__start_SC: - return variables_offset + (MAX_GLOBAL_VARIABLES*WORDSIZE); + return variables_offset + (MAX_ZCODE_GLOBAL_VARS*WORDSIZE); case array__end_SC: return static_memory_offset; + case dictionary_table_SC: + return dictionary_offset; + case grammar_table_SC: + return static_memory_offset; case highest_attribute_number_SC: return no_attributes-1; @@ -706,7 +712,8 @@ static int32 value_of_system_constant_z(int t) return(0); } -/* Must match the switch statement below */ +/* List used to generate gameinfo.dbg. + Must match the switch statement below. */ int glulx_system_constant_list[] = { classes_table_SC, identifiers_table_SC, @@ -765,7 +772,15 @@ extern int32 value_of_system_constant(int t) return value_of_system_constant_g(t); } -static int evaluate_term(token_data t, assembly_operand *o) +extern char *name_of_system_constant(int t) +{ + if (t < 0 || t >= NO_SYSTEM_CONSTANTS) { + return "???"; + } + return system_constants.keywords[t]; +} + +static int evaluate_term(const token_data *t, assembly_operand *o) { /* If the given token is a constant, evaluate it into the operand. For now, the identifiers are considered variables. @@ -774,13 +789,12 @@ static int evaluate_term(token_data t, assembly_operand *o) int32 v; - o->marker = t.marker; - o->symtype = t.symtype; - o->symflags = t.symflags; + o->marker = t->marker; + o->symindex = t->symindex; - switch(t.type) + switch(t->type) { case LARGE_NUMBER_TT: - v = t.value; + v = t->value; if (!glulx_mode) { if (v < 0) v = v + 0x10000; o->type = LONG_CONSTANT_OT; @@ -792,7 +806,7 @@ static int evaluate_term(token_data t, assembly_operand *o) } return(TRUE); case SMALL_NUMBER_TT: - v = t.value; + v = t->value; if (!glulx_mode) { if (v < 0) v = v + 0x10000; o->type = SHORT_CONSTANT_OT; @@ -809,7 +823,7 @@ static int evaluate_term(token_data t, assembly_operand *o) o->type = LONG_CONSTANT_OT; else o->type = CONSTANT_OT; - o->value = dictionary_add(t.text, 0x80, 0, 0); + o->value = dictionary_add(t->text, 0x80, 0, 0); return(TRUE); case DQ_TT: /* Create as a static string */ @@ -817,14 +831,14 @@ static int evaluate_term(token_data t, assembly_operand *o) o->type = LONG_CONSTANT_OT; else o->type = CONSTANT_OT; - o->value = compile_string(t.text, STRCTX_GAME); + o->value = compile_string(t->text, STRCTX_GAME); return(TRUE); case VARIABLE_TT: if (!glulx_mode) { o->type = VARIABLE_OT; } else { - if (t.value >= MAX_LOCAL_VARIABLES) { + if (t->value >= MAX_LOCAL_VARIABLES) { o->type = GLOBALVAR_OT; } else { @@ -833,21 +847,21 @@ static int evaluate_term(token_data t, assembly_operand *o) o->type = LOCALVAR_OT; } } - o->value = t.value; + o->value = t->value; return(TRUE); case SYSFUN_TT: if (!glulx_mode) { o->type = VARIABLE_OT; - o->value = t.value + 256; + o->value = t->value + 256; } else { o->type = SYSFUN_OT; - o->value = t.value; + o->value = t->value; } - system_function_usage[t.value] = 1; + system_function_usage[t->value] = 1; return(TRUE); case ACTION_TT: - *o = action_of_name(t.text); + *o = action_of_name(t->text); return(TRUE); case SYSTEM_CONSTANT_TT: /* Certain system constants depend only on the @@ -856,7 +870,7 @@ static int evaluate_term(token_data t, assembly_operand *o) them immediately. */ if (!glulx_mode) { o->type = LONG_CONSTANT_OT; - switch(t.value) + switch(t->value) { case version_number_SC: o->type = SHORT_CONSTANT_OT; @@ -873,6 +887,8 @@ static int evaluate_term(token_data t, assembly_operand *o) case dict_par3_SC: o->type = SHORT_CONSTANT_OT; o->marker = 0; + if (ZCODE_LESS_DICT_DATA) + error("#dict_par3 is unavailable when ZCODE_LESS_DICT_DATA is set"); v = (version_number==3)?6:8; break; case lowest_attribute_number_SC: case lowest_action_number_SC: @@ -893,7 +909,7 @@ static int evaluate_term(token_data t, assembly_operand *o) o->type = SHORT_CONSTANT_OT; o->marker = 0; v = oddeven_packing_switch; break; default: - v = t.value; + v = t->value; o->marker = INCON_MV; break; } @@ -901,7 +917,7 @@ static int evaluate_term(token_data t, assembly_operand *o) } else { o->type = CONSTANT_OT; - switch(t.value) + switch(t->value) { /* The three dict_par flags point at the lower byte of the flag field, because the library is written @@ -943,7 +959,7 @@ static int evaluate_term(token_data t, assembly_operand *o) /* ###fix: need to fill more of these in! */ default: - v = t.value; + v = t->value; o->marker = INCON_MV; break; } @@ -957,35 +973,40 @@ static int evaluate_term(token_data t, assembly_operand *o) /* --- Emitter ------------------------------------------------------------- */ -expression_tree_node *ET; +expression_tree_node *ET; /* Allocated to ET_used */ +static memory_list ET_memlist; static int ET_used; extern void clear_expression_space(void) { ET_used = 0; } -static assembly_operand *emitter_stack; -static int *emitter_markers; -static int *emitter_bracket_counts; +typedef struct emitterstackinfo_s { + assembly_operand op; + int marker; + int bracket_count; +} emitterstackinfo; #define FUNCTION_VALUE_MARKER 1 #define ARGUMENT_VALUE_MARKER 2 #define OR_VALUE_MARKER 3 +static emitterstackinfo *emitter_stack; /* Allocated to emitter_sp */ +static memory_list emitter_stack_memlist; static int emitter_sp; static int is_property_t(int symbol_type) { return ((symbol_type == PROPERTY_T) || (symbol_type == INDIVIDUAL_PROPERTY_T)); } -static void mark_top_of_emitter_stack(int marker, token_data t) +static void mark_top_of_emitter_stack(int marker, const token_data *t) { if (emitter_sp < 1) { compiler_error("SR error: Attempt to add a marker to the top of an empty emitter stack"); return; } if (expr_trace_level >= 2) { printf("Marking top of emitter stack (which is "); - print_operand(emitter_stack[emitter_sp-1]); + print_operand(&emitter_stack[emitter_sp-1].op, FALSE); printf(") as "); switch(marker) { @@ -1004,21 +1025,20 @@ static void mark_top_of_emitter_stack(int marker, token_data t) } printf("\n"); } - if (emitter_markers[emitter_sp-1]) + if (emitter_stack[emitter_sp-1].marker) { if (marker == ARGUMENT_VALUE_MARKER) { warning("Ignoring spurious leading comma"); return; } - error_named("Missing operand for", t.text); - if (emitter_sp == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); - emitter_markers[emitter_sp] = 0; - emitter_bracket_counts[emitter_sp] = 0; - emitter_stack[emitter_sp] = zero_operand; + error_named("Missing operand for", t->text); + ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1); + emitter_stack[emitter_sp].marker = 0; + emitter_stack[emitter_sp].bracket_count = 0; + emitter_stack[emitter_sp].op = zero_operand; emitter_sp++; } - emitter_markers[emitter_sp-1] = marker; + emitter_stack[emitter_sp-1].marker = marker; } static void add_bracket_layer_to_emitter_stack(int depth) @@ -1026,7 +1046,7 @@ static void add_bracket_layer_to_emitter_stack(int depth) if (emitter_sp < depth + 1) return; if (expr_trace_level >= 2) printf("Adding bracket layer\n"); - ++emitter_bracket_counts[emitter_sp-depth-1]; + ++emitter_stack[emitter_sp-depth-1].bracket_count; } static void remove_bracket_layer_from_emitter_stack() @@ -1034,46 +1054,47 @@ static void remove_bracket_layer_from_emitter_stack() if (emitter_sp < 2) return; if (expr_trace_level >= 2) printf("Removing bracket layer\n"); - if (emitter_bracket_counts[emitter_sp-2] <= 0) + if (emitter_stack[emitter_sp-2].bracket_count <= 0) { compiler_error("SR error: Attempt to remove a nonexistent bracket layer from the emitter stack"); return; } - --emitter_bracket_counts[emitter_sp-2]; + --emitter_stack[emitter_sp-2].bracket_count; } -static void emit_token(token_data t) +static void emit_token(const token_data *t) { assembly_operand o1, o2; int arity, stack_size, i; int op_node_number, operand_node_number, previous_node_number; int32 x = 0; if (expr_trace_level >= 2) - { printf("Output: %-19s%21s ", t.text, ""); + { printf("Output: %-19s%21s ", t->text, ""); for (i=0; itype == SUBOPEN_TT) return; stack_size = 0; while ((stack_size < emitter_sp) && - !emitter_markers[emitter_sp-stack_size-1] && - !emitter_bracket_counts[emitter_sp-stack_size-1]) + !emitter_stack[emitter_sp-stack_size-1].marker && + !emitter_stack[emitter_sp-stack_size-1].bracket_count) stack_size++; - if (t.type == SUBCLOSE_TT) - { if (stack_size < emitter_sp && emitter_bracket_counts[emitter_sp-stack_size-1]) + if (t->type == SUBCLOSE_TT) + { if (stack_size < emitter_sp && emitter_stack[emitter_sp-stack_size-1].bracket_count) { if (stack_size == 0) { error("No expression between brackets '(' and ')'"); - emitter_stack[emitter_sp] = zero_operand; - emitter_markers[emitter_sp] = 0; - emitter_bracket_counts[emitter_sp] = 0; - ++emitter_sp; + ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1); + emitter_stack[emitter_sp].op = zero_operand; + emitter_stack[emitter_sp].marker = 0; + emitter_stack[emitter_sp].bracket_count = 0; + emitter_sp++; } else if (stack_size < 1) compiler_error("SR error: emitter stack empty in subexpression"); @@ -1084,14 +1105,14 @@ static void emit_token(token_data t) return; } - if (t.type != OP_TT) - { emitter_markers[emitter_sp] = 0; - emitter_bracket_counts[emitter_sp] = 0; + if (t->type != OP_TT) + { + ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1); + emitter_stack[emitter_sp].marker = 0; + emitter_stack[emitter_sp].bracket_count = 0; - if (emitter_sp == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); - if (!evaluate_term(t, &(emitter_stack[emitter_sp++]))) - compiler_error_named("Emit token error:", t.text); + if (!evaluate_term(t, &(emitter_stack[emitter_sp++].op))) + compiler_error_named("Emit token error:", t->text); return; } @@ -1099,85 +1120,85 @@ static void emit_token(token_data t) call, since we ignore spurious leading commas in function argument lists) with no intervening brackets. Function calls are variadic, so we don't apply argument-separating commas. */ - if (t.value == COMMA_OP && + if (t->value == COMMA_OP && stack_size < emitter_sp && - (emitter_markers[emitter_sp-stack_size-1] == ARGUMENT_VALUE_MARKER || - emitter_markers[emitter_sp-stack_size-1] == FUNCTION_VALUE_MARKER) && - !emitter_bracket_counts[emitter_sp-stack_size-1]) + (emitter_stack[emitter_sp-stack_size-1].marker == ARGUMENT_VALUE_MARKER || + emitter_stack[emitter_sp-stack_size-1].marker == FUNCTION_VALUE_MARKER) && + !emitter_stack[emitter_sp-stack_size-1].bracket_count) { if (expr_trace_level >= 2) printf("Treating comma as argument-separating\n"); return; } - if (t.value == OR_OP) + if (t->value == OR_OP) return; arity = 1; - if (t.value == FCALL_OP) + if (t->value == FCALL_OP) { if (expr_trace_level >= 3) { printf("FCALL_OP finds marker stack: "); - for (x=0; x= 256 && - emitter_stack[emitter_sp-arity].value < 288)) - { int index = emitter_stack[emitter_sp-arity].value; + emitter_stack[emitter_sp-arity].op.type == VARIABLE_OT && + emitter_stack[emitter_sp-arity].op.value >= 256 && + emitter_stack[emitter_sp-arity].op.value < 288)) + { int index = emitter_stack[emitter_sp-arity].op.value; if(!glulx_mode) index -= 256; if(index >= 0 && index < NUMBER_SYSTEM_FUNCTIONS) error_named("System function name used as a value:", system_functions.keywords[index]); else compiler_error("Found unnamed system function used as a value"); - emitter_stack[emitter_sp-arity] = zero_operand; + emitter_stack[emitter_sp-arity].op = zero_operand; } ++arity; } } else { arity = 1; - if (operators[t.value].usage == IN_U) arity = 2; + if (operators[t->value].usage == IN_U) arity = 2; - if (operators[t.value].precedence == 3) + if (operators[t->value].precedence == 3) { arity = 2; x = emitter_sp-1; - if(!emitter_markers[x] && !emitter_bracket_counts[x]) - { for (--x; emitter_markers[x] == OR_VALUE_MARKER && !emitter_bracket_counts[x]; --x) + if(!emitter_stack[x].marker && !emitter_stack[x].bracket_count) + { for (--x; emitter_stack[x].marker == OR_VALUE_MARKER && !emitter_stack[x].bracket_count; --x) { ++arity; ++stack_size; } - for (;x >= 0 && !emitter_markers[x] && !emitter_bracket_counts[x]; --x) + for (;x >= 0 && !emitter_stack[x].marker && !emitter_stack[x].bracket_count; --x) ++stack_size; } } if (arity > stack_size) - { error_named("Missing operand for", t.text); + { error_named("Missing operand for", t->text); while (arity > stack_size) - { if (emitter_sp == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); - emitter_markers[emitter_sp] = 0; - emitter_bracket_counts[emitter_sp] = 0; - emitter_stack[emitter_sp] = zero_operand; + { ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1); + emitter_stack[emitter_sp].marker = 0; + emitter_stack[emitter_sp].bracket_count = 0; + emitter_stack[emitter_sp].op = zero_operand; emitter_sp++; stack_size++; } } } - /* pseudo-typecheck in 6.30 */ + /* pseudo-typecheck in 6.30: catch an unqualified property name */ for (i = 1; i <= arity; i++) { - o1 = emitter_stack[emitter_sp - i]; - if (is_property_t(o1.symtype) ) { - switch(t.value) + o1 = emitter_stack[emitter_sp - i].op; + if ((o1.symindex >= 0) + && is_property_t(symbols[o1.symindex].type)) { + switch(t->value) { case FCALL_OP: case SETEQUALS_OP: case NOTEQUAL_OP: @@ -1189,7 +1210,11 @@ static void emit_token(token_data t) case PROPERTY_OP: if (i < arity) break; case GE_OP: case LE_OP: - if ((i < arity) && (o1.symflags & STAR_SFLAG)) break; + /* Direction properties "n_to", etc *are* compared + in some libraries. They have STAR_SFLAG to tell us + to skip the warning. */ + if ((i < arity) + && (symbols[o1.symindex].flags & STAR_SFLAG)) break; default: warning("Property name in expression is not qualified by object"); } @@ -1198,9 +1223,9 @@ static void emit_token(token_data t) switch(arity) { case 1: - o1 = emitter_stack[emitter_sp - 1]; + o1 = emitter_stack[emitter_sp - 1].op; if ((o1.marker == 0) && is_constant_ot(o1.type)) - { switch(t.value) + { switch(t->value) { case UNARY_MINUS_OP: x = -o1.value; goto FoldConstant; case ARTNOT_OP: if (!glulx_mode) @@ -1216,8 +1241,8 @@ static void emit_token(token_data t) break; case 2: - o1 = emitter_stack[emitter_sp - 2]; - o2 = emitter_stack[emitter_sp - 1]; + o1 = emitter_stack[emitter_sp - 2].op; + o2 = emitter_stack[emitter_sp - 1].op; if ((o1.marker == 0) && (o2.marker == 0) && is_constant_ot(o1.type) && is_constant_ot(o2.type)) @@ -1232,7 +1257,7 @@ static void emit_token(token_data t) ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value; } - switch(t.value) + switch(t->value) { case PLUS_OP: x = ov1 + ov2; goto FoldConstantC; case MINUS_OP: x = ov1 - ov2; goto FoldConstantC; @@ -1242,7 +1267,7 @@ static void emit_token(token_data t) if (ov2 == 0) error("Division of constant by zero"); else - if (t.value == DIVIDE_OP) { + if (t->value == DIVIDE_OP) { if (ov2 < 0) { ov1 = -ov1; ov2 = -ov2; @@ -1291,13 +1316,32 @@ static void emit_token(token_data t) } } + + /* We can also fold logical operations if they are certain + to short-circuit. The right-hand argument is skipped even + if it's non-constant or has side effects. */ + + if ((o1.marker == 0) + && is_constant_ot(o1.type)) { + + if (t->value == LOGAND_OP && o1.value == 0) + { + x = 0; + goto FoldConstant; + } + + if (t->value == LOGOR_OP && o1.value != 0) + { + x = 1; + goto FoldConstant; + } + } } + ensure_memory_list_available(&ET_memlist, ET_used+1); op_node_number = ET_used++; - if (op_node_number == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); - ET[op_node_number].operator_number = t.value; + ET[op_node_number].operator_number = t->value; ET[op_node_number].up = -1; ET[op_node_number].down = -1; ET[op_node_number].right = -1; @@ -1311,14 +1355,14 @@ static void emit_token(token_data t) if (expr_trace_level >= 3) printf("i=%d, emitter_sp=%d, arity=%d, ETU=%d\n", i, emitter_sp, arity, ET_used); - if (emitter_stack[i].type == EXPRESSION_OT) - operand_node_number = emitter_stack[i].value; + if (emitter_stack[i].op.type == EXPRESSION_OT) + operand_node_number = emitter_stack[i].op.value; else - { operand_node_number = ET_used++; - if (operand_node_number == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); + { + ensure_memory_list_available(&ET_memlist, ET_used+1); + operand_node_number = ET_used++; ET[operand_node_number].down = -1; - ET[operand_node_number].value = emitter_stack[i]; + ET[operand_node_number].value = emitter_stack[i].op; } ET[operand_node_number].up = op_node_number; ET[operand_node_number].right = -1; @@ -1333,11 +1377,11 @@ static void emit_token(token_data t) emitter_sp = emitter_sp - arity + 1; - emitter_stack[emitter_sp - 1].type = EXPRESSION_OT; - emitter_stack[emitter_sp - 1].value = op_node_number; + emitter_stack[emitter_sp - 1].op.type = EXPRESSION_OT; + emitter_stack[emitter_sp - 1].op.value = op_node_number; + emitter_stack[emitter_sp - 1].op.marker = 0; emitter_stack[emitter_sp - 1].marker = 0; - emitter_markers[emitter_sp - 1] = 0; - emitter_bracket_counts[emitter_sp - 1] = 0; + emitter_stack[emitter_sp - 1].bracket_count = 0; /* Remove the marker for the brackets implied by operator precedence */ remove_bracket_layer_from_emitter_stack(); @@ -1352,7 +1396,7 @@ static void emit_token(token_data t) { char folding_error[40]; int32 ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value; int32 ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value; - switch(t.value) + switch(t->value) { case PLUS_OP: sprintf(folding_error, "%d + %d = %d", ov1, ov2, x); @@ -1382,28 +1426,28 @@ the range -32768 to +32767:", folding_error); if (!glulx_mode) { if (x<256) - emitter_stack[emitter_sp - 1].type = SHORT_CONSTANT_OT; - else emitter_stack[emitter_sp - 1].type = LONG_CONSTANT_OT; + emitter_stack[emitter_sp - 1].op.type = SHORT_CONSTANT_OT; + else emitter_stack[emitter_sp - 1].op.type = LONG_CONSTANT_OT; } else { if (x == 0) - emitter_stack[emitter_sp - 1].type = ZEROCONSTANT_OT; + emitter_stack[emitter_sp - 1].op.type = ZEROCONSTANT_OT; else if (x >= -128 && x <= 127) - emitter_stack[emitter_sp - 1].type = BYTECONSTANT_OT; + emitter_stack[emitter_sp - 1].op.type = BYTECONSTANT_OT; else if (x >= -32768 && x <= 32767) - emitter_stack[emitter_sp - 1].type = HALFCONSTANT_OT; + emitter_stack[emitter_sp - 1].op.type = HALFCONSTANT_OT; else - emitter_stack[emitter_sp - 1].type = CONSTANT_OT; + emitter_stack[emitter_sp - 1].op.type = CONSTANT_OT; } - emitter_stack[emitter_sp - 1].value = x; + emitter_stack[emitter_sp - 1].op.value = x; + emitter_stack[emitter_sp - 1].op.marker = 0; emitter_stack[emitter_sp - 1].marker = 0; - emitter_markers[emitter_sp - 1] = 0; - emitter_bracket_counts[emitter_sp - 1] = 0; + emitter_stack[emitter_sp - 1].bracket_count = 0; if (expr_trace_level >= 2) { printf("Folding constant to: "); - print_operand(emitter_stack[emitter_sp - 1]); + print_operand(&emitter_stack[emitter_sp - 1].op, FALSE); printf("\n"); } @@ -1419,9 +1463,7 @@ static void show_node(int n, int depth, int annotate) for (j=0; j<2*depth+2; j++) printf(" "); if (ET[n].down == -1) - { print_operand(ET[n].value); - if (annotate && (ET[n].value.marker != 0)) - printf(" [%s]", describe_mv(ET[n].value.marker)); + { print_operand(&ET[n].value, annotate); printf("\n"); } else @@ -1443,9 +1485,7 @@ static void show_node(int n, int depth, int annotate) extern void show_tree(assembly_operand AO, int annotate) { if (AO.type == EXPRESSION_OT) show_node(AO.value, 0, annotate); else - { printf("Constant: "); print_operand(AO); - if (annotate && (AO.marker != 0)) - printf(" [%s]", describe_mv(AO.marker)); + { printf("Constant: "); print_operand(&AO, annotate); printf("\n"); } } @@ -1624,10 +1664,25 @@ static void delete_negations(int n, int context) (etc) to delete the ~~ operator from the tree. Since this is depth first, the ~~ being deleted has no ~~s beneath it, which - is important to make "negate_condition" work. */ + is important to make "negate_condition" work. + + We also do the check for (x <= y or z) here. This must be done + before negate_condition. + */ int i; + if (ET[n].operator_number == LE_OP || ET[n].operator_number == GE_OP) { + if (ET[n].down != -1 + && ET[ET[n].down].right != -1 + && ET[ET[ET[n].down].right].right != -1) { + if (ET[n].operator_number == LE_OP) + warning("The behavior of (<= or) may be unexpected."); + else + warning("The behavior of (>= or) may be unexpected."); + } + } + if (ET[n].right != -1) delete_negations(ET[n].right, context); if (ET[n].down == -1) return; delete_negations(ET[n].down, context); @@ -1654,9 +1709,9 @@ static void insert_exp_to_cond(int n, int context) if (ET[n].down == -1) { if (context==CONDITION_CONTEXT) - { new = ET_used++; - if (new == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); + { + ensure_memory_list_available(&ET_memlist, ET_used+1); + new = ET_used++; ET[new] = ET[n]; ET[n].down = new; ET[n].operator_number = NONZERO_OP; ET[new].up = n; ET[new].right = -1; @@ -1677,9 +1732,8 @@ static void insert_exp_to_cond(int n, int context) default: if (context != CONDITION_CONTEXT) break; + ensure_memory_list_available(&ET_memlist, ET_used+1); new = ET_used++; - if (new == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); ET[new] = ET[n]; ET[n].down = new; ET[n].operator_number = NONZERO_OP; ET[new].up = n; ET[new].right = -1; @@ -1736,9 +1790,8 @@ static void func_args_on_stack(int n, int context) || ET[fnaddr].value.value == INDIRECT_SYSF || ET[fnaddr].value.value == GLK_SYSF))) { if (etoken_num_children(pn) > (unsigned int)(opnum == FCALL_OP ? 4:3)) { + ensure_memory_list_available(&ET_memlist, ET_used+1); new = ET_used++; - if (new == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); ET[new] = ET[n]; ET[n].down = new; ET[n].operator_number = PUSH_OP; @@ -1759,9 +1812,8 @@ static assembly_operand check_conditions(assembly_operand AO, int context) if (AO.type != EXPRESSION_OT) { if (context != CONDITION_CONTEXT) return AO; + ensure_memory_list_available(&ET_memlist, ET_used+1); n = ET_used++; - if (n == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); ET[n].down = -1; ET[n].up = -1; ET[n].right = -1; @@ -1782,7 +1834,8 @@ static assembly_operand check_conditions(assembly_operand AO, int context) /* --- Shift-reduce parser ------------------------------------------------- */ static int sr_sp; -static token_data *sr_stack; +static token_data *sr_stack; /* Allocated to sr_sp */ +static memory_list sr_stack_memlist; extern assembly_operand parse_expression(int context) { @@ -1866,6 +1919,7 @@ extern assembly_operand parse_expression(int context) previous_token.type = ENDEXP_TT; previous_token.value = 0; + ensure_memory_list_available(&sr_stack_memlist, 1); sr_sp = 1; sr_stack[0] = previous_token; @@ -1905,7 +1959,7 @@ extern assembly_operand parse_expression(int context) return AO; } - AO = emitter_stack[0]; + AO = emitter_stack[0].op; if (AO.type == EXPRESSION_OT) { if (expr_trace_level >= 3) { printf("Tree before lvalue checking:\n"); @@ -1917,7 +1971,9 @@ extern assembly_operand parse_expression(int context) ET[AO.value].up = -1; } else { - if ((context != CONSTANT_CONTEXT) && is_property_t(AO.symtype) + if ((context != CONSTANT_CONTEXT) + && (AO.symindex >= 0) + && is_property_t(symbols[AO.symindex].type) && (arrow_allowed) && (!bare_prop_allowed)) warning("Bare property name found. \"self.prop\" intended?"); } @@ -1934,7 +1990,7 @@ extern assembly_operand parse_expression(int context) return(AO); } - switch(find_prec(a,b)) + switch(find_prec(&a,&b)) { case e5: /* Associativity error */ error_named("Brackets mandatory to clarify order of:", @@ -1942,14 +1998,13 @@ extern assembly_operand parse_expression(int context) case LOWER_P: case EQUAL_P: - if (sr_sp == MAX_EXPRESSION_NODES) - memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES); + ensure_memory_list_available(&sr_stack_memlist, sr_sp+1); sr_stack[sr_sp++] = b; switch(b.type) { case SUBOPEN_TT: if (sr_sp >= 2 && sr_stack[sr_sp-2].type == OP_TT && sr_stack[sr_sp-2].value == FCALL_OP) - mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, b); + mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, &b); else add_bracket_layer_to_emitter_stack(0); break; @@ -1958,7 +2013,7 @@ extern assembly_operand parse_expression(int context) case OR_OP: if (sr_stack[sr_sp-2].type == OP_TT && operators[sr_stack[sr_sp-2].value].precedence == 3) - mark_top_of_emitter_stack(OR_VALUE_MARKER, b); + mark_top_of_emitter_stack(OR_VALUE_MARKER, &b); else { error("'or' not between values to the right of a condition"); /* Convert to + for error recovery purposes */ @@ -1974,7 +2029,7 @@ extern assembly_operand parse_expression(int context) if (shallowest_open_bracket_index > 0 && sr_stack[shallowest_open_bracket_index-1].type == OP_TT && sr_stack[shallowest_open_bracket_index-1].value == FCALL_OP) - { mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, b); + { mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, &b); break; } /* Non-argument-separating commas get treated like any other operator; we fall through to the default case. */ @@ -1992,9 +2047,9 @@ extern assembly_operand parse_expression(int context) case GREATER_P: do { pop = sr_stack[sr_sp - 1]; - emit_token(pop); + emit_token(&pop); sr_sp--; - } while (find_prec(sr_stack[sr_sp-1], pop) != LOWER_P); + } while (find_prec(&sr_stack[sr_sp-1], &pop) != LOWER_P); break; case e1: /* Missing operand error */ @@ -2056,7 +2111,12 @@ extern void init_expressp_vars(void) { int i; /* make_operands(); */ make_lexical_interface_tables(); - for (i=0;i<32;i++) system_function_usage[i] = 0; + for (i=0; i