summaryrefslogtreecommitdiff
path: root/switch.c
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2007-09-06 20:00:36 -0400
committerSøren Sandmann <sandmann@redhat.com>2007-09-06 20:00:36 -0400
commite6dd81037f39cf197e1b50bf867521a54722d24f (patch)
tree3aa08d18e1c8f669379d31ccea9b86889001e7c0 /switch.c
parent8a69bd70d7193253325bb94195a9e049921112d3 (diff)
Evaluate expressions in switch cases
Diffstat (limited to 'switch.c')
-rw-r--r--switch.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/switch.c b/switch.c
index 305914c..a7f2e2b 100644
--- a/switch.c
+++ b/switch.c
@@ -50,16 +50,27 @@ compare_cases (const void *a,
}
static gboolean
-constant_expression (ast_expression_t *expr)
+constant_expression (ast_expression_t *expr,
+ value_t *value)
{
+ value_t left;
+ value_t right;
+ value_t result;
+
g_assert (((ast_t *)expr)->common.type == AST_EXPRESSION);
switch (expr->common.type)
{
case AST_INT_LITERAL_EXPRESSION:
+ value->int32_val = expr->int_literal.value;
+ break;
+
case AST_BOOL_LITERAL_EXPRESSION:
+ value->bool_val = expr->bool_literal.value;
+ break;
+
case AST_NULL_EXPRESSION:
- return TRUE;
+ value->pointer_val = NULL;
break;
case AST_IDENTIFIER_EXPRESSION:
@@ -78,29 +89,43 @@ constant_expression (ast_expression_t *expr)
break;
case AST_UNARY_EXPRESSION:
- if (!constant_expression (expr->unary.expr))
+ if (!constant_expression (expr->unary.expr, &result))
return FALSE;
+
+ evaluate_unary_operator (expr->unary.operator,
+ expr->unary.expr->common.type_spec, &result,
+ expr->common.type_spec, value);
break;
case AST_BINARY_EXPRESSION:
- if (!constant_expression (expr->binary.left))
+ if (!constant_expression (expr->binary.left, &left))
return FALSE;
- if (!constant_expression (expr->binary.right))
+ if (!constant_expression (expr->binary.right, &right))
return FALSE;
+
+ evaluate_binary_operator (expr->binary.operator,
+ expr->binary.left->common.type_spec, &left,
+ expr->binary.right->common.type_spec, &right,
+ expr->common.type_spec, value);
break;
case AST_TERNARY_EXPRESSION:
- if (!constant_expression (expr->ternary.cond))
+ if (!constant_expression (expr->ternary.cond, &result))
return FALSE;
/* FIXME: we could require only the taken branch to be constant */
-
- if (!constant_expression (expr->ternary.then_expr))
+
+ if (!constant_expression (expr->ternary.then_expr, &left))
return FALSE;
- if (!constant_expression (expr->ternary.else_expr))
+ if (!constant_expression (expr->ternary.else_expr, &right))
return FALSE;
+
+ if (result.bool_val)
+ *value = left;
+ else
+ *value = right;
break;
}
@@ -120,10 +145,12 @@ check_constant_case_expressions (ast_t *ast)
if (ast_is (ast, AST_CASE, AST_EXPRESSION_CASE))
{
+ value_t value;
+
/* FIXME: check that we are dealing with a constant expression,
* and store the value of that expression in the case clause
*/
- if (!constant_expression (ast->case_.expression.expression))
+ if (!constant_expression (ast->case_.expression.expression, &value))
{
g_print ("Expression in case clause must be constant\n");