summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2015-12-07 15:14:26 +0800
committerTing-Wei Lan <lantw44@gmail.com>2015-12-07 15:14:26 +0800
commit2b4a6e4b93c45fc5e23f311ccfef09f218267ca1 (patch)
tree428657f675258ea69f7b2fa072913e70df52ef80
parent310a8951557a6e6ac200ba08301ab7ef77a64686 (diff)
downloadcompiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar.gz
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar.bz2
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar.lz
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar.xz
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.tar.zst
compiler2015-2b4a6e4b93c45fc5e23f311ccfef09f218267ca1.zip
Write results to AST nodes when evaluating constant expressions
This commit also add a macro to reduce duplicate code.
-rw-r--r--src/ast.h31
-rw-r--r--src/semantic-analysis.c150
2 files changed, 93 insertions, 88 deletions
diff --git a/src/ast.h b/src/ast.h
index cfbfda1..2f16680 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -143,6 +143,37 @@ typedef struct CcmmcAst_struct {
};
} CcmmcAst;
+static inline bool ccmmc_ast_expr_get_is_constant(CcmmcAst *expr_node) {
+ return expr_node->value_expr.is_const_eval;
+}
+static inline void ccmmc_ast_expr_set_is_constant(CcmmcAst *expr_node, bool value) {
+ expr_node->value_expr.is_const_eval = value;
+}
+static inline bool ccmmc_ast_expr_get_is_int(CcmmcAst *expr_node) {
+ return expr_node->type_value == CCMMC_AST_VALUE_INT;
+}
+static inline void ccmmc_ast_expr_set_is_int(CcmmcAst *expr_node) {
+ expr_node->type_value = CCMMC_AST_VALUE_INT;
+}
+static inline bool ccmmc_ast_expr_get_is_float(CcmmcAst *expr_node) {
+ return expr_node->type_value == CCMMC_AST_VALUE_FLOAT;
+}
+static inline void ccmmc_ast_expr_set_is_float(CcmmcAst *expr_node) {
+ expr_node->type_value = CCMMC_AST_VALUE_FLOAT;
+}
+static inline int ccmmc_ast_expr_get_int(CcmmcAst *expr_node) {
+ return expr_node->value_expr.const_int;
+}
+static inline void ccmmc_ast_expr_set_int(CcmmcAst *expr_node, int value) {
+ expr_node->value_expr.const_int = value;
+}
+static inline float ccmmc_ast_expr_get_float(CcmmcAst *expr_node) {
+ return expr_node->value_expr.const_float;
+}
+static inline void ccmmc_ast_expr_set_float(CcmmcAst *expr_node, float value) {
+ expr_node->value_expr.const_float = value;
+}
+
CcmmcAst *ccmmc_ast_new (CcmmcAstNodeType type_node,
size_t line_number);
CcmmcAst *ccmmc_ast_new_id (char *lexeme,
diff --git a/src/semantic-analysis.c b/src/semantic-analysis.c
index f8652b2..d3a7de4 100644
--- a/src/semantic-analysis.c
+++ b/src/semantic-analysis.c
@@ -24,100 +24,70 @@ static CcmmcValueConst eval_const_expr(CcmmcAst *expr) {
if (left.kind == CCMMC_KIND_CONST_ERROR ||
right.kind == CCMMC_KIND_CONST_ERROR)
return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_ERROR };
+
+#define EVAL_AND_RETURN_CONST(op) \
+ do { \
+ if (left.kind == CCMMC_KIND_CONST_INT) { \
+ if (right.kind == CCMMC_KIND_CONST_INT) { \
+ int result = left.const_int op right.const_int; \
+ ccmmc_ast_expr_set_is_constant(expr, true); \
+ ccmmc_ast_expr_set_is_int(expr); \
+ ccmmc_ast_expr_set_int(expr, result); \
+ return (CcmmcValueConst){ \
+ .kind = CCMMC_KIND_CONST_INT, .const_int = result }; \
+ } else if (right.kind == CCMMC_KIND_CONST_FLOAT) { \
+ float left_value = left.const_int; \
+ float right_value = right.const_float; \
+ float result = left_value op right_value; \
+ ccmmc_ast_expr_set_is_constant(expr, true); \
+ ccmmc_ast_expr_set_is_float(expr); \
+ ccmmc_ast_expr_set_float(expr, result); \
+ return (CcmmcValueConst){ \
+ .kind = CCMMC_KIND_CONST_FLOAT, .const_float = result }; \
+ } \
+ assert(false); \
+ } else if (left.kind == CCMMC_KIND_CONST_FLOAT) { \
+ if (right.kind == CCMMC_KIND_CONST_INT) { \
+ float left_value = left.const_float; \
+ float right_value = right.const_int; \
+ float result = left_value op right_value; \
+ ccmmc_ast_expr_set_is_constant(expr, true); \
+ ccmmc_ast_expr_set_is_float(expr); \
+ ccmmc_ast_expr_set_float(expr, result); \
+ return (CcmmcValueConst){ \
+ .kind = CCMMC_KIND_CONST_FLOAT, .const_float = result }; \
+ } else if (right.kind == CCMMC_KIND_CONST_FLOAT) { \
+ float result = left.const_float op right.const_float; \
+ ccmmc_ast_expr_set_is_constant(expr, true); \
+ ccmmc_ast_expr_set_is_float(expr); \
+ ccmmc_ast_expr_set_float(expr, result); \
+ return (CcmmcValueConst){ \
+ .kind = CCMMC_KIND_CONST_FLOAT, .const_float = result }; \
+ } \
+ assert(false); \
+ } \
+ } while (false)
+
switch (expr->value_expr.op_binary) {
case CCMMC_KIND_OP_BINARY_ADD:
- if (left.kind == CCMMC_KIND_CONST_INT) {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_INT,
- .const_int = left.const_int + right.const_int };
- } else {
- float left_value = left.const_int;
- float right_value = right.const_float;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value + right_value };
- }
- } else {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- float left_value = left.const_float;
- float right_value = right.const_int;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value + right_value };
- } else {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left.const_float + right.const_float };
- }
- }
+ EVAL_AND_RETURN_CONST(+);
+ assert(false);
case CCMMC_KIND_OP_BINARY_SUB:
- if (left.kind == CCMMC_KIND_CONST_INT) {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_INT,
- .const_int = left.const_int - right.const_int };
- } else {
- float left_value = left.const_int;
- float right_value = right.const_float;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value - right_value };
- }
- } else {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- float left_value = left.const_float;
- float right_value = right.const_int;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value - right_value };
- } else {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left.const_float - right.const_float };
- }
- }
+ EVAL_AND_RETURN_CONST(-);
+ assert(false);
case CCMMC_KIND_OP_BINARY_MUL:
- if (left.kind == CCMMC_KIND_CONST_INT) {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_INT,
- .const_int = left.const_int * right.const_int };
- } else {
- float left_value = left.const_int;
- float right_value = right.const_float;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value * right_value };
- }
- } else {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- float left_value = left.const_float;
- float right_value = right.const_int;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value * right_value };
- } else {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left.const_float * right.const_float };
- }
- }
+ EVAL_AND_RETURN_CONST(*);
+ assert(false);
case CCMMC_KIND_OP_BINARY_DIV:
- if (left.kind == CCMMC_KIND_CONST_INT) {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- if (right.const_int == 0) {
- fprintf(stderr, ERROR("Integer division by zero."),
- expr->line_number);
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_ERROR };
- }
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_INT,
- .const_int = left.const_int / right.const_int };
- } else {
- float left_value = left.const_int;
- float right_value = right.const_float;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value / right_value };
- }
- } else {
- if (right.kind == CCMMC_KIND_CONST_INT) {
- float left_value = left.const_float;
- float right_value = right.const_int;
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left_value / right_value };
- } else {
- return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_FLOAT,
- .const_float = left.const_float / right.const_float };
- }
+ if (left.kind == CCMMC_KIND_CONST_INT &&
+ right.kind == CCMMC_KIND_CONST_INT &&
+ right.const_int == 0) {
+ fprintf(stderr, ERROR("Integer division by zero."),
+ expr->line_number);
+ return (CcmmcValueConst){ .kind = CCMMC_KIND_CONST_ERROR };
}
+ EVAL_AND_RETURN_CONST(/);
+ assert(false);
case CCMMC_KIND_OP_BINARY_EQ:
case CCMMC_KIND_OP_BINARY_GE:
case CCMMC_KIND_OP_BINARY_LE:
@@ -129,6 +99,10 @@ static CcmmcValueConst eval_const_expr(CcmmcAst *expr) {
default:
assert(false);
}
+#undef EVAL_CONST_INT_INT
+#undef EVAL_CONST_INT_FLOAT
+#undef EVAL_CONST_FLOAT_INT
+#undef EVAL_CONST_FLOAT_FLOAT
}
static size_t *get_array_size(CcmmcAst *id_array, size_t *array_dimension)