Use function pointer tables instead of switch.

This seems to be better for complicated code. switch seems to be better
suited for relatively simple code.
This commit is contained in:
Bill Currie 2011-01-22 11:36:56 +09:00
parent 2f09efe547
commit 246778b5de

View file

@ -93,24 +93,22 @@ get_op_string (int op)
} }
} }
typedef void (*print_f) (expr_t *, int, int);
static void _print_expr (expr_t *e, int level, int id);
static void static void
_print_expr (expr_t *e, int level, int id) print_error (expr_t *e, int level, int id)
{ {
const char *label = "???";
const char *shape = "ellipse";
int indent = level * 2 + 2; int indent = level * 2 + 2;
if (!e) {
printf ("%*se_%p [label=\"(null)\"];\n", indent, "", e); printf ("%*se_%p [label=\"(error)\"];\n", indent, "", e);
return;
} }
if (e->printid == id) // already printed this expression
return; static void
e->printid = id; print_state (expr_t *e, int level, int id)
switch (e->type) { {
case ex_error: int indent = level * 2 + 2;
label = "(error)";
break;
case ex_state:
_print_expr (e->e.state.frame, level, id); _print_expr (e->e.state.frame, level, id);
_print_expr (e->e.state.think, level, id); _print_expr (e->e.state.think, level, id);
if (e->e.state.step) if (e->e.state.step)
@ -118,12 +116,16 @@ _print_expr (expr_t *e, int level, int id)
printf ("%*se_%p:f -> e_%p;\n", indent, "", e, e->e.state.frame); printf ("%*se_%p:f -> e_%p;\n", indent, "", e, e->e.state.frame);
printf ("%*se_%p:t -> e_%p;\n", indent, "", e, e->e.state.think); printf ("%*se_%p:t -> e_%p;\n", indent, "", e, e->e.state.think);
if (e->e.state.step) if (e->e.state.step)
printf ("%*se_%p:s -> e_%p;\n", indent, "", printf ("%*se_%p:s -> e_%p;\n", indent, "", e, e->e.state.step);
e, e->e.state.step); printf ("%*se_%p [label=\"<f>state|<t>think|<s>step\",shape=record];\n",
shape = "record"; indent, "", e);
label = va ("<f>state|<t>think|<s>step;"); }
break;
case ex_bool: static void
print_bool (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
_print_expr (e->e.bool.e, level, id); _print_expr (e->e.bool.e, level, id);
if (e->e.bool.e->type == ex_block && e->e.bool.e->e.block.head) { if (e->e.bool.e->type == ex_block && e->e.bool.e->e.block.head) {
expr_t *se; expr_t *se;
@ -137,20 +139,27 @@ _print_expr (expr_t *e, int level, int id)
} else { } else {
printf ("%*se_%p -> e_%p;\n", indent, "", e, e->e.bool.e); printf ("%*se_%p -> e_%p;\n", indent, "", e, e->e.bool.e);
} }
label = "<bool>"; printf ("%*se_%p [label=\"<bool>\"];\n", indent, "", e);
break; }
case ex_label:
static void
print_label (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
if (e->next) if (e->next)
printf ("%*se_%p -> e_%p " printf ("%*se_%p -> e_%p "
"[constraint=false,style=dashed];\n", indent, "", "[constraint=false,style=dashed];\n", indent, "",
e, e->next); e, e->next);
label = e->e.label.name; printf ("%*se_%p [label=\"%s\"];\n", indent, "", e, e->e.label.name);
break; }
case ex_block:
static void
print_block (expr_t *e, int level, int id)
{ {
int indent = level * 2 + 2;
expr_t *se; expr_t *se;
label = "<block>";
if (e->e.block.result) { if (e->e.block.result) {
_print_expr (e->e.block.result, level + 1, id); _print_expr (e->e.block.result, level + 1, id);
printf ("%*se_%p -> e_%p;\n", indent, "", printf ("%*se_%p -> e_%p;\n", indent, "",
@ -166,18 +175,21 @@ _print_expr (expr_t *e, int level, int id)
if ((se->type == ex_uexpr && se->e.expr.op == 'g') if ((se->type == ex_uexpr && se->e.expr.op == 'g')
|| se->type == ex_label || se->type == ex_bool) || se->type == ex_label || se->type == ex_bool)
continue; continue;
printf ("%*se_%p -> e_%p " printf ("%*se_%p -> e_%p [constraint=false,style=dashed];\n",
"[constraint=false,style=dashed];\n", indent, "", indent, "", se, se->next);
se, se->next);
} }
if (se && se->type == ex_label && e->next) if (se && se->type == ex_label && e->next)
printf ("%*se_%p -> e_%p " printf ("%*se_%p -> e_%p [constraint=false,style=dashed];\n",
"[constraint=false,style=dashed];\n", indent, "", indent, "", se, e->next);
se, e->next);
printf ("%*s}\n", indent, ""); printf ("%*s}\n", indent, "");
printf ("%*se_%p [label=\"<block>\"];\n", indent, "", e);
} }
break;
case ex_expr: static void
print_subexpr (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
if (e->e.expr.op == 'c') { if (e->e.expr.op == 'c') {
expr_t *p; expr_t *p;
int i; int i;
@ -208,24 +220,52 @@ _print_expr (expr_t *e, int level, int id)
printf ("%*se_%p -> e_%p [label=\"r\"];\n", indent, "", printf ("%*se_%p -> e_%p [label=\"r\"];\n", indent, "",
e, e->e.expr.e2); e, e->e.expr.e2);
} }
label = get_op_string (e->e.expr.op); printf ("%*se_%p [label=\"%s\"];\n", indent, "", e,
break; get_op_string (e->e.expr.op));
case ex_uexpr: }
static void
print_uexpr (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
if (e->e.expr.op != 'g') if (e->e.expr.op != 'g')
_print_expr (e->e.expr.e1, level, id); _print_expr (e->e.expr.e1, level, id);
printf ("%*se_%p -> e_%p;\n", indent, "", e, e->e.expr.e1); printf ("%*se_%p -> e_%p;\n", indent, "", e, e->e.expr.e1);
label = get_op_string (e->e.expr.op); printf ("%*se_%p [label=\"%s\"];\n", indent, "", e,
break; get_op_string (e->e.expr.op));
case ex_symbol: }
label = e->e.symbol->name;
break; static void
case ex_temp: print_symbol (expr_t *e, int level, int id)
label = va ("tmp_%p", e); {
break; int indent = level * 2 + 2;
case ex_nil:
label = "nil"; printf ("%*se_%p [label=\"%s\"];\n", indent, "", e, e->e.symbol->name);
break; }
case ex_value:
static void
print_temp (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
printf ("%*se_%p [label=\"tmp_%p\"];\n", indent, "", e, e);
}
static void
print_nil (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
printf ("%*se_%p [label=\"nil\"];\n", indent, "", e);
}
static void
print_value (expr_t *e, int level, int id)
{
int indent = level * 2 + 2;
const char *label = "?!?";
switch (e->e.value.type) { switch (e->e.value.type) {
case ev_string: case ev_string:
label = va ("\\\"%s\\\"", e->e.value.v.string_val); label = va ("\\\"%s\\\"", e->e.value.v.string_val);
@ -267,14 +307,50 @@ _print_expr (expr_t *e, int level, int id)
label = va ("%d", e->e.value.v.short_val); label = va ("%d", e->e.value.v.short_val);
break; break;
case ev_void: case ev_void:
label = "<void>";
break;
case ev_invalid: case ev_invalid:
label = "<invalid>";
break;
case ev_type_count: case ev_type_count:
internal_error (e, "weird expression type"); label = "<type_count>";
break;
} }
printf ("%*se_%p [label=\"%s\"];\n", indent, "", e, label);
} }
if (label)
printf ("%*se_%p [label=\"%s\",shape=%s];\n", indent, "", static void
e, label, shape); _print_expr (expr_t *e, int level, int id)
{
static print_f print_funcs[] = {
print_error,
print_state,
print_bool,
print_label,
print_block,
print_subexpr,
print_uexpr,
print_symbol,
print_temp,
print_nil,
print_value,
};
int indent = level * 2 + 2;
if (!e) {
printf ("%*se_%p [label=\"(null)\"];\n", indent, "", e);
return;
}
if (e->printid == id) // already printed this expression
return;
e->printid = id;
if (e->type < 0 || e->type > ex_value) {
printf ("%*se_%p [label=\"(bad expr type)\"];\n", indent, "", e);
return;
}
print_funcs [e->type] (e, level, id);
} }
void void