Make some expression tree operations more generic.

This commit is contained in:
Olaf Seibert 2021-11-14 14:56:51 +01:00
parent 6a3642e49a
commit 2aa43f17f7
3 changed files with 113 additions and 90 deletions

View File

@ -201,57 +201,52 @@ unsigned get_register(
void implicit_gbl(
EX_TREE *value)
{
if (pass)
if (pass || !value)
return; /* Only do this in first pass */
switch (value->type) {
case EX_UNDEFINED_SYM:
{
if (!(value->data.symbol->flags & SYMBOLFLAG_LOCAL)) {
/* Unless it's a local symbol, */
if (enabl_gbl) {
/* either make the undefined symbol into an
implicit global */
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_GLOBAL,
&absolute_section, &implicit_st);
} else {
/* or add it to the undefined symbol table,
purely for listing purposes.
It also works to add it to symbol_st,
all code is carefully made for that. */
switch (num_subtrees(value)) {
case 0:
switch (value->type) {
case EX_UNDEFINED_SYM:
{
if (!(value->data.symbol->flags & SYMBOLFLAG_LOCAL)) {
/* Unless it's a local symbol, */
if (enabl_gbl) {
/* either make the undefined symbol into an
implicit global */
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_GLOBAL,
&absolute_section, &implicit_st);
} else {
/* or add it to the undefined symbol table,
purely for listing purposes.
It also works to add it to symbol_st,
all code is carefully made for that. */
#define ADD_UNDEFINED_SYMBOLS_TO_MAIN_SYMBOL_TABLE 0
#if ADD_UNDEFINED_SYMBOLS_TO_MAIN_SYMBOL_TABLE
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED,
&absolute_section, &symbol_st);
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED,
&absolute_section, &symbol_st);
#else
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED,
&absolute_section, &undefined_st);
add_sym(value->data.symbol->label, 0, SYMBOLFLAG_UNDEFINED,
&absolute_section, &undefined_st);
#endif
}
}
}
break;
case EX_LIT:
case EX_SYM:
case EX_TEMP_SYM: // Impossible on this pass
return;
default:
break;
}
break;
case EX_LIT:
case EX_SYM:
case EX_TEMP_SYM: // Impossible on this pass
return;
case EX_ADD:
case EX_SUB:
case EX_MUL:
case EX_DIV:
case EX_AND:
case EX_OR:
case EX_LSH:
case 2:
implicit_gbl(value->data.child.right);
/* FALLS THROUGH */
case EX_COM:
case EX_NEG:
case 1:
implicit_gbl(value->data.child.left);
break;
case EX_ERR:
if (value->data.child.left)
implicit_gbl(value->data.child.left);
break;
}
}

112
extree.c
View File

@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "extree.h" /* my own definitions */
@ -130,31 +131,23 @@ void print_tree(
fputc('\n', printfile);
}
/* free_tree frees an expression tree. */
/* num_subtrees tells you how many subtrees this EX_TREE has. */
void free_tree(
int num_subtrees(
EX_TREE *tp)
{
switch (tp->type) {
case EX_UNDEFINED_SYM:
case EX_TEMP_SYM:
free(tp->data.symbol->label);
free(tp->data.symbol);
break;
case EX_LIT:
case EX_SYM:
case EX_LIT:
return 0;
break;
case EX_COM:
case EX_NEG:
free_tree(tp->data.child.left);
break;
case EX_ERR:
if (tp->data.child.left)
free_tree(tp->data.child.left);
break;
return 1;
case EX_ADD:
case EX_SUB:
@ -163,10 +156,46 @@ void free_tree(
case EX_AND:
case EX_OR:
case EX_LSH:
free_tree(tp->data.child.left);
free_tree(tp->data.child.right);
break;
return 2;
}
return 0;
}
/* free_tree frees an expression tree. */
void free_tree(
EX_TREE *tp)
{
if (!tp)
return;
switch (num_subtrees(tp)) {
case 0:
switch (tp->type) {
case EX_UNDEFINED_SYM:
case EX_TEMP_SYM:
free(tp->data.symbol->label);
free(tp->data.symbol);
break;
case EX_SYM:
case EX_LIT:
break;
default:
assert(0);
break;
}
break;
case 2:
free_tree(tp->data.child.right);
/* FALLTHROUGH */
case 1:
free_tree(tp->data.child.left);
break;
}
free(tp);
}
@ -228,37 +257,34 @@ EX_TREE *dup_tree(
res = new_ex_tree(tp->type);
res->cp = tp->cp;
switch (tp->type) {
case EX_UNDEFINED_SYM:
case EX_TEMP_SYM:
res->data.symbol = dup_symbol(tp->data.symbol);
break;
switch (num_subtrees(tp)) {
case 0:
switch (tp->type) {
case EX_UNDEFINED_SYM:
case EX_TEMP_SYM:
res->data.symbol = dup_symbol(tp->data.symbol);
break;
/* The symbol reference in EX_SYM is not freed in free_tree() */
case EX_SYM:
res->data.symbol = tp->data.symbol;
break;
/* The symbol reference in EX_SYM is not freed in free_tree() */
case EX_SYM:
res->data.symbol = tp->data.symbol;
break;
case EX_LIT:
res->data.lit = tp->data.lit;
break;
case EX_LIT:
res->data.lit = tp->data.lit;
break;
case EX_COM:
case EX_NEG:
case EX_ERR:
res->data.child.left = dup_tree(tp->data.child.left);
break;
case EX_ADD:
case EX_SUB:
case EX_MUL:
case EX_DIV:
case EX_AND:
case EX_OR:
case EX_LSH:
res->data.child.left = dup_tree(tp->data.child.left);
res->data.child.right = dup_tree(tp->data.child.right);
default:
assert(0);
break;
}
break;
case 2:
res->data.child.right = dup_tree(tp->data.child.right);
/* FALLTHROUGH */
case 1:
res->data.child.left = dup_tree(tp->data.child.left);
break;
}
return res;

View File

@ -8,7 +8,8 @@ typedef struct ex_tree {
enum ex_type { EX_LIT = 1,
/* Expression is a literal value */
EX_SYM = 2,
/* Expression has a symbol reference */
/* Expression has a symbol reference
* (symbol from symbol table, so not freed) */
EX_UNDEFINED_SYM = 3,
/* Expression is undefined sym reference */
EX_TEMP_SYM = 4,
@ -18,22 +19,22 @@ typedef struct ex_tree {
/* One's complement */
EX_NEG = 6,
/* Negate */
EX_ERR = 7,
EX_ERR = 8,
/* Expression with an error */
EX_ADD = 8,
EX_ADD = 9,
/* Add */
EX_SUB = 9,
EX_SUB = 10,
/* Subtract */
EX_MUL = 10,
EX_MUL = 11,
/* Multiply */
EX_DIV = 11,
EX_DIV = 12,
/* Divide */
EX_AND = 12,
EX_AND = 13,
/* bitwise and */
EX_OR = 13,
EX_OR = 14,
/* bitwise or */
EX_LSH = 14
EX_LSH = 15,
/* left shift */
} type;
@ -67,7 +68,8 @@ EX_TREE *new_ex_bin(
EX_TREE *new_ex_una(
int type,
EX_TREE *left);
int num_subtrees(
EX_TREE *tp);
EX_TREE *evaluate(
EX_TREE *tp,
int flags);