/* ------------------------------------------------------------------------- */
/* "expressc" : The expression code generator */
/* */
-/* Part of Inform 6.40 */
-/* copyright (c) Graham Nelson 1993 - 2022 */
+/* Part of Inform 6.42 */
+/* copyright (c) Graham Nelson 1993 - 2024 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
assembly_operand zero_ao, max_ao, size_ao, en_ao, type_ao, an_ao,
index_ao;
- int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE, from_module = FALSE;
+ int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE;
INITAO(&zero_ao);
INITAO(&size_ao);
error("Cannot write to a static array");
}
- if (size_ao.value==-1)
- from_module=TRUE;
+ if (size_ao.value==-1) {
+ /* This case was originally meant for module linking.
+ It should no longer be possible. */
+ compiler_error("Array size cannot be negative");
+ }
else {
- from_module=FALSE;
type_ao = zero_ao; type_ao.value = arrays[y].type;
if ((!is_systemfile()))
/* If we recognise AO1 as arising textually from a declared
array, we can check bounds explicitly. */
- if ((AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV) && (!from_module))
+ if ((AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV))
{
int passed_label = next_label++, failed_label = next_label++,
final_label = next_label++;
/* Test if inside the "Class" object... */
INITAOTV(&AO3, BYTECONSTANT_OT, GOBJFIELD_PARENT());
assembleg_3(aload_gc, AO, AO3, stack_pointer);
- ln = symbol_index("Class", -1);
- AO3.value = symbols[ln].value;
- AO3.marker = OBJECT_MV;
- AO3.type = CONSTANT_OT;
+ ln = get_symbol_index("Class");
+ if (ln < 0) {
+ error("No 'Class' object found");
+ AO3 = zero_operand;
+ }
+ else {
+ AO3.value = symbols[ln].value;
+ AO3.marker = OBJECT_MV;
+ AO3.type = CONSTANT_OT;
+ }
assembleg_2_branch(jne_gc, stack_pointer, AO3, passed_label);
}
}
else {
/* Build the symbol for "Object" */
- ln = symbol_index("Object", -1);
- AO2.value = symbols[ln].value;
- AO2.marker = OBJECT_MV;
- AO2.type = CONSTANT_OT;
+ ln = get_symbol_index("Object");
+ if (ln < 0) {
+ error("No 'Object' object found");
+ AO2 = zero_operand;
+ }
+ else {
+ AO2.value = symbols[ln].value;
+ AO2.marker = OBJECT_MV;
+ AO2.type = CONSTANT_OT;
+ }
if (check_sp) {
/* Push "Object" */
assembleg_store(AO1, AO2);
assembleg_2(random_gc, AO, stack_pointer);
assembleg_3(aload_gc, AO2, stack_pointer, Result);
}
+ else if (is_constant_ot(ET[ET[below].right].value.type) && ET[ET[below].right].value.marker == 0) {
+ /* One argument, value known at compile time */
+ int32 arg = ET[ET[below].right].value.value; /* signed */
+ if (arg > 0) {
+ assembly_operand AO;
+ INITAO(&AO);
+ AO.value = arg;
+ set_constant_ot(&AO);
+ assembleg_2(random_gc,
+ AO, stack_pointer);
+ assembleg_3(add_gc, stack_pointer, one_operand,
+ Result);
+ }
+ else {
+ /* This handles zero or negative */
+ assembly_operand AO;
+ INITAO(&AO);
+ AO.value = -arg;
+ set_constant_ot(&AO);
+ assembleg_1(setrandom_gc,
+ AO);
+ assembleg_store(Result, zero_operand);
+ }
+ }
else {
+ /* One argument, not known at compile time */
+ int ln, ln2;
+ assembleg_store(temp_var1, ET[ET[below].right].value);
+ ln = next_label++;
+ ln2 = next_label++;
+ assembleg_2_branch(jle_gc, temp_var1, zero_operand, ln);
assembleg_2(random_gc,
- ET[ET[below].right].value, stack_pointer);
+ temp_var1, stack_pointer);
assembleg_3(add_gc, stack_pointer, one_operand,
Result);
+ assembleg_0_branch(jump_gc, ln2);
+ assemble_label_no(ln);
+ assembleg_2(neg_gc, temp_var1, stack_pointer);
+ assembleg_1(setrandom_gc,
+ stack_pointer);
+ assembleg_store(Result, zero_operand);
+ assemble_label_no(ln2);
}
break;
}
if (expr_trace_level >= 2)
- { printf("Raw parse tree:\n"); show_tree(AO, FALSE);
+ { printf("Raw parse tree:\n"); show_tree(&AO, FALSE);
}
if (context == CONDITION_CONTEXT)
default: printf("* ILLEGAL *"); break;
}
printf(" context with annotated tree:\n");
- show_tree(AO, TRUE);
+ show_tree(&AO, TRUE);
}
generate_code_from(AO.value, (context==VOID_CONTEXT));