/* ------------------------------------------------------------------------- */
/* "expressp" : The expression parser */
/* */
-/* Copyright (c) Graham Nelson 1993 - 2020 */
-/* */
-/* This file is part of Inform. */
+/* 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 */
array_init_ambiguity, action_ambiguity,
etoken_count, inserting_token, bracket_level;
-extern int *variable_usage;
-
-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,
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;
}
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:
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;
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;
current_token.marker = 0;
break;
}
- if (sflags[symbol] & SYSTEM_SFLAG)
+ if (symbols[symbol].flags & SYSTEM_SFLAG)
current_token.marker = 0;
current_token.value = v;
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;
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);
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)
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;
|| (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");
}
}
};
-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,
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;
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:
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;
/* --- 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,
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)
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;
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,
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.
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;
}
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;
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 */
o->type = LONG_CONSTANT_OT;
else
o->type = CONSTANT_OT;
- o->value = compile_string(t.text, FALSE, FALSE);
+ 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 {
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
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;
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:
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;
}
}
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
/* ###fix: need to fill more of these in! */
default:
- v = t.value;
+ v = t->value;
o->marker = INCON_MV;
break;
}
/* --- 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)
{
}
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)
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()
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; i<emitter_sp; i++)
- { print_operand(emitter_stack[i]); printf(" ");
- if (emitter_markers[i] == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
- if (emitter_markers[i] == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
- if (emitter_markers[i] == OR_VALUE_MARKER) printf(":OR ");
- if (emitter_bracket_counts[i]) printf(":BRACKETS(%d) ", emitter_bracket_counts[i]);
+ { print_operand(&emitter_stack[i].op, FALSE); printf(" ");
+ if (emitter_stack[i].marker == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
+ if (emitter_stack[i].marker == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
+ if (emitter_stack[i].marker == OR_VALUE_MARKER) printf(":OR ");
+ if (emitter_stack[i].bracket_count) printf(":BRACKETS(%d) ", emitter_stack[i].bracket_count);
}
printf("\n");
}
- if (t.type == SUBOPEN_TT) return;
+ if (t->type == 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");
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;
}
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<emitter_sp; x++) printf("%d ", emitter_markers[x]);
+ for (x=0; x<emitter_sp; x++) printf("%d ", emitter_stack[x].marker);
printf("\n");
}
- if (emitter_markers[emitter_sp-1] == ARGUMENT_VALUE_MARKER)
+ if (emitter_stack[emitter_sp-1].marker == ARGUMENT_VALUE_MARKER)
warning("Ignoring spurious trailing comma");
- while (emitter_markers[emitter_sp-arity] != FUNCTION_VALUE_MARKER)
+ while (emitter_stack[emitter_sp-arity].marker != FUNCTION_VALUE_MARKER)
{
if ((glulx_mode &&
- emitter_stack[emitter_sp-arity].type == SYSFUN_OT) ||
+ emitter_stack[emitter_sp-arity].op.type == SYSFUN_OT) ||
(!glulx_mode &&
- emitter_stack[emitter_sp-arity].type == VARIABLE_OT &&
- emitter_stack[emitter_sp-arity].value >= 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:
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");
}
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)
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))
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;
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;
}
}
+
+ /* 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;
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;
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();
{ 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);
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");
}
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
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");
}
}
if ((below != -1) && (ET[below].right != -1))
{ int n = ET[below].right, flag = FALSE;
+ /* Can we handle this dot operator as a native @get_prop (etc)
+ opcode? Only if we recognize the property value as a declared
+ common property constant. */
if ((ET[n].down == -1)
&& ((ET[n].value.type == LONG_CONSTANT_OT)
|| (ET[n].value.type == SHORT_CONSTANT_OT))
&& ((ET[n].value.value > 0) && (ET[n].value.value < 64))
- && ((!module_switch) || (ET[n].value.marker == 0)))
+ && (!module_switch)
+ && (ET[n].value.marker == 0))
flag = TRUE;
if (!flag)
(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);
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;
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;
|| 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;
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;
/* --- 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)
{
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;
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");
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?");
}
return(AO);
}
- switch(find_prec(a,b))
+ switch(find_prec(&a,&b))
{
case e5: /* Associativity error */
error_named("Brackets mandatory to clarify order of:",
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;
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 */
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. */
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 */
{ int i;
/* make_operands(); */
make_lexical_interface_tables();
- for (i=0;i<32;i++) system_function_usage[i] = 0;
+ for (i=0; i<NUMBER_SYSTEM_FUNCTIONS; i++)
+ system_function_usage[i] = 0;
+
+ ET = NULL;
+ emitter_stack = NULL;
+ sr_stack = NULL;
}
extern void expressp_begin_pass(void)
}
extern void expressp_allocate_arrays(void)
-{ ET = my_calloc(sizeof(expression_tree_node), MAX_EXPRESSION_NODES,
+{
+ initialise_memory_list(&ET_memlist,
+ sizeof(expression_tree_node), 100, (void**)&ET,
"expression parse trees");
- emitter_markers = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
- "emitter markers");
- emitter_bracket_counts = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
- "emitter bracket layer counts");
- emitter_stack = my_calloc(sizeof(assembly_operand), MAX_EXPRESSION_NODES,
- "emitter stack");
- sr_stack = my_calloc(sizeof(token_data), MAX_EXPRESSION_NODES,
+
+ initialise_memory_list(&emitter_stack_memlist,
+ sizeof(emitterstackinfo), 100, (void**)&emitter_stack,
+ "expression stack");
+
+ initialise_memory_list(&sr_stack_memlist,
+ sizeof(token_data), 100, (void**)&sr_stack,
"shift-reduce parser stack");
}
extern void expressp_free_arrays(void)
-{ my_free(&ET, "expression parse trees");
- my_free(&emitter_markers, "emitter markers");
- my_free(&emitter_bracket_counts, "emitter bracket layer counts");
- my_free(&emitter_stack, "emitter stack");
- my_free(&sr_stack, "shift-reduce parser stack");
+{
+ deallocate_memory_list(&ET_memlist);
+
+ deallocate_memory_list(&emitter_stack_memlist);
+
+ deallocate_memory_list(&sr_stack_memlist);
}
/* ========================================================================= */