support "const literal string" in 'case' for 'switch'
authoryu.dongliang <18588496441@163.com>
Wed, 2 Oct 2024 04:30:07 +0000 (12:30 +0800)
committeryu.dongliang <18588496441@163.com>
Wed, 2 Oct 2024 04:30:57 +0000 (12:30 +0800)
18 files changed:
core/scf_3ac.c
core/scf_basic_block.c
core/scf_expr.c
core/scf_expr.h
core/scf_node.c
core/scf_operator_handler_3ac.c
core/scf_optimizer.c
core/scf_type_cast.c
core/scf_variable.h
examples/switch_string.c [new file with mode: 0644]
native/x64/scf_x64.c
parse/scf_dfa_for.c
parse/scf_dfa_if.c
parse/scf_dfa_switch.c
parse/scf_dfa_while.c
parse/scf_operator_handler_const.c
parse/scf_operator_handler_semantic.c
parse/scf_parse.c

index 9d82a6253ee92d5821eda7ab61eaa8e2980d7409..3a13affadd107e55a859f46cb7ffe7ba64a07e6d 100644 (file)
@@ -450,16 +450,16 @@ static void _3ac_print_node(scf_node_t* node)
 {
        if (scf_type_is_var(node->type)) {
                if (node->var->w) {
-                       printf("v_%d_%d/%s",
-                                       node->var->w->line, node->var->w->pos, node->var->w->text->data);
+                       printf("v_%d_%d/%s/%#lx",
+                                       node->var->w->line, node->var->w->pos, node->var->w->text->data, 0xffff & (uintptr_t)node->var);
                } else {
                        printf("v_%#lx", 0xffff & (uintptr_t)node->var);
                }
        } else if (scf_type_is_operator(node->type)) {
                if (node->result) {
                        if (node->result->w) {
-                               printf("v_%d_%d/%s",
-                                               node->result->w->line, node->result->w->pos, node->result->w->text->data);
+                               printf("v_%d_%d/%s/%#lx",
+                                               node->result->w->line, node->result->w->pos, node->result->w->text->data, 0xffff & (uintptr_t)node->result);
                        } else
                                printf("v/%#lx", 0xffff & (uintptr_t)node->result);
                }
index 786e3b8e6415242cf3c697b8c85e3f40c8113200..8e39c9b64dcd13b7947236e643ad05d5f503007e 100644 (file)
@@ -194,10 +194,10 @@ void scf_basic_block_print(scf_basic_block_t* bb, scf_list_t* sentinel)
        if (bb) {
 #define SCF_BB_PRINT(h) \
                do { \
-                       scf_list_t* l; \
-                       for (l = scf_list_head(&bb->h); l != scf_list_sentinel(&bb->h); \
-                                       l = scf_list_next(l)) { \
-                               scf_3ac_code_t* c = scf_list_data(l, scf_3ac_code_t, list); \
+                       scf_3ac_code_t* c; \
+                       scf_list_t*     l; \
+                       for (l = scf_list_head(&bb->h); l != scf_list_sentinel(&bb->h); l = scf_list_next(l)) { \
+                                = scf_list_data(l, scf_3ac_code_t, list); \
                                scf_3ac_code_print(c, sentinel); \
                        } \
                } while (0)
@@ -259,7 +259,7 @@ void scf_basic_block_print_list(scf_list_t* h)
        for (l = scf_list_head(h); l != scf_list_sentinel(h); l = scf_list_next(l)) {
                bb = scf_list_data(l, scf_basic_block_t, list);
 
-               printf("\033[33mbasic_block: %p, index: %d, dfo: %d, cmp_flag: %d, call_flag: %d, group: %d, loop: %d, dereference_flag: %d, ret_flag: %d\033[0m\n",
+               printf("\033[34mbasic_block: %p, index: %d, dfo: %d, cmp_flag: %d, call_flag: %d, group: %d, loop: %d, dereference_flag: %d, ret_flag: %d\033[0m\n",
                                bb, bb->index, bb->dfo, bb->cmp_flag, bb->call_flag, bb->group_flag, bb->loop_flag, bb->dereference_flag, bb->ret_flag);
 
                scf_basic_block_print(bb, sentinel);
@@ -280,12 +280,7 @@ void scf_basic_block_print_list(scf_list_t* h)
                                printf("next     : %p, index: %d\n", bb2, bb2->index);
                        }
                }
-#if 0
-               if (bb->dominators_normal) {
-                       for (i = 0; i < bb->dominators_normal->size; i++)
-                               printf("dominator: %p\n", bb->dominators_normal->data[i]);
-               }
-#endif
+
                if (bb->dn_status_initeds) {
                        printf("inited: \n");
                        for (i = 0; i < bb->dn_status_initeds->size; i++) {
@@ -295,7 +290,7 @@ void scf_basic_block_print_list(scf_list_t* h)
                        }
                        printf("\n");
                }
-#if 1
+
                if (bb->ds_malloced) {
                        printf("auto gc: \n");
                        for (i = 0; i < bb->ds_malloced->size; i++) {
@@ -307,7 +302,7 @@ void scf_basic_block_print_list(scf_list_t* h)
                        }
                        printf("\n");
                }
-#endif
+
                if (bb->entry_dn_actives) {
                        for (i = 0; i < bb->entry_dn_actives->size; i++) {
                                dn =        bb->entry_dn_actives->data[i];
index c3c94ac547a2d8d4bcaf7be58f60399b5a7e30c6..b2377c32e266c75f9fef430537a8a48651664ed8 100644 (file)
@@ -3,17 +3,12 @@
 scf_expr_t* scf_expr_alloc()
 {
        scf_expr_t* e = calloc(1, sizeof(scf_expr_t));
-       if (!e) {
-               scf_loge("expr alloc failed");
+       if (!e)
                return NULL;
-       }
 
        e->nodes = calloc(1, sizeof(scf_node_t*));
        if (!e->nodes) {
-               scf_loge("expr nodes alloc failed");
-
                free(e);
-               e = NULL;
                return NULL;
        }
 
@@ -29,7 +24,6 @@ int scf_expr_copy(scf_node_t* e2, scf_node_t* e)
        for (i = 0; i < e->nb_nodes; i++) {
 
                node = scf_node_clone(e->nodes[i]);
-
                if (!node)
                        return -ENOMEM;
 
@@ -66,7 +60,7 @@ void scf_expr_free(scf_expr_t* e)
        }
 }
 
-static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child)
+static int __expr_node_add_node(scf_node_t** pparent, scf_node_t* child)
 {
        scf_node_t* parent = *pparent;
        if (!parent) {
@@ -79,10 +73,10 @@ static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child)
 
                if (parent->op->nb_operands > parent->nb_nodes)
                        return scf_node_add_child(parent, child);
-               else {
-                       assert(parent->nb_nodes >= 1);
-                       return _scf_expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child);
-               }
+
+               assert(parent->nb_nodes >= 1);
+               return __expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child);
+
        } else if (parent->priority < child->priority) {
                assert(child->op);
 
@@ -90,37 +84,34 @@ static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child)
                        assert(child->op->nb_operands > child->nb_nodes);
 
                child->parent = parent->parent;
-               if (scf_node_add_child(child, parent) < 0) {
-                       scf_loge("expr nodes alloc failed");
+               if (scf_node_add_child(child, parent) < 0)
                        return -1;
-               }
+
                *pparent = child;
                return 0;
-       } else {
-               // parent->priority == child->priority
-               assert(parent->op);
-               assert(child->op);
+       }
 
-               if (SCF_OP_ASSOCIATIVITY_LEFT == child->op->associativity) {
-                       if (child->op->nb_operands > 0)
-                               assert(child->op->nb_operands > child->nb_nodes);
-
-                       child->parent = parent->parent;
-                       scf_node_add_child(child, parent); // add parent to child's child node
-                       *pparent = child; // child is the new parent node
-                       return 0;
-               } else {
-                       if (parent->op->nb_operands > parent->nb_nodes)
-                               return scf_node_add_child(parent, child);
-                       else {
-                               assert(parent->nb_nodes >= 1);
-                               return _scf_expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child);
-                       }
-               }
+       // parent->priority == child->priority
+       assert(parent->op);
+       assert(child->op);
+
+       if (SCF_OP_ASSOCIATIVITY_LEFT == child->op->associativity) {
+               if (child->op->nb_operands > 0)
+                       assert(child->op->nb_operands > child->nb_nodes);
+
+               child->parent = parent->parent;
+
+               scf_node_add_child(child, parent); // add parent to child's child node
+
+               *pparent = child; // child is the new parent node
+               return 0;
        }
 
-       scf_loge("\n");
-       return -1;
+       if (parent->op->nb_operands > parent->nb_nodes)
+               return scf_node_add_child(parent, child);
+
+       assert(parent->nb_nodes >= 1);
+       return __expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child);
 }
 
 int scf_expr_add_node(scf_expr_t* e, scf_node_t* node)
@@ -128,10 +119,10 @@ int scf_expr_add_node(scf_expr_t* e, scf_node_t* node)
        assert(e);
        assert(node);
 
-       if (scf_type_is_var(node->type)) {
+       if (scf_type_is_var(node->type))
                node->priority = -1;
 
-       else if (scf_type_is_operator(node->type)) {
+       else if (scf_type_is_operator(node->type)) {
 
                node->op = scf_find_base_operator_by_type(node->type);
                if (!node->op) {
@@ -144,13 +135,31 @@ int scf_expr_add_node(scf_expr_t* e, scf_node_t* node)
                return -1;
        }
 
-       if (_scf_expr_node_add_node(&(e->nodes[0]), node) < 0) {
-               scf_loge("\n");
+       if (__expr_node_add_node(&(e->nodes[0]), node) < 0)
                return -1;
-       }
 
        e->nodes[0]->parent = e;
        e->nb_nodes = 1;
        return 0;       
 }
 
+void scf_expr_simplify(scf_expr_t** pe)
+{
+       scf_expr_t** pp = pe;
+       scf_expr_t*  e;
+
+       while (SCF_OP_EXPR == (*pp)->type) {
+               e  = *pp;
+               pp = &(e->nodes[0]);
+       }
+
+       if (pp != pe) {
+               e   = *pp;
+               *pp = NULL;
+
+               e->parent = (*pe)->parent;
+
+               scf_expr_free(*pe);
+               *pe = e;
+       }
+}
index 7029b688304a030aafb24f5ea1bc8c667fff8749..de8ca607d9b2ef1de5b4903be16ad268808df1ab 100644 (file)
@@ -3,12 +3,13 @@
 
 #include"scf_node.h"
 
-typedef scf_node_t     scf_expr_t; // expr is a node
+typedef scf_node_t  scf_expr_t; // expr is a node
 
-scf_expr_t*                    scf_expr_alloc();
-scf_expr_t*                    scf_expr_clone(scf_expr_t* e);
-void                           scf_expr_free(scf_expr_t* expr);
-int                                    scf_expr_add_node(scf_expr_t* expr, scf_node_t* node);
+scf_expr_t*         scf_expr_alloc();
+scf_expr_t*         scf_expr_clone(scf_expr_t* e);
+void                scf_expr_free (scf_expr_t* e);
 
-#endif
+int                 scf_expr_add_node(scf_expr_t*  e, scf_node_t* node);
+void                scf_expr_simplify(scf_expr_t** pe);
 
+#endif
index dd111da619ff0652225aa1dfb7e40678676fa714..03de08deec8eeec53275f05cd99f8b5d674d7364 100644 (file)
@@ -134,10 +134,8 @@ int scf_node_add_child(scf_node_t* parent, scf_node_t* child)
                return -EINVAL;
 
        void* p = realloc(parent->nodes, sizeof(scf_node_t*) * (parent->nb_nodes + 1));
-       if (!p) {
-               scf_loge("realloc failed\n");
+       if (!p)
                return -ENOMEM;
-       }
 
        parent->nodes = p;
        parent->nodes[parent->nb_nodes++] = child;
index 5dcd74b1d11df6b17a1fb4703045229555a16abf..e5c389772838c7adcc844380ff035f609dc631be 100644 (file)
@@ -1140,12 +1140,17 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void
                                        return -1;
                                }
 
-                               scf_node_t* srcs[2] = {e, e2};
+                               if (SCF_OP_CALL == e2->type)
+                                       cmp = scf_3ac_code_NN(SCF_OP_3AC_TEQ, NULL, 0, &e2, 1);
+                               else {
+                                       scf_node_t* srcs[2] = {e, e2};
+
+                                       cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2);
+                               }
+                               scf_list_add_tail(d->_3ac_list_head, &cmp->list);
 
-                               cmp  = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2);
                                jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL);
 
-                               scf_list_add_tail(d->_3ac_list_head, &cmp->list);
                                scf_list_add_tail(d->_3ac_list_head, &jnot->list);
 
                                scf_vector_add(up_branch_ops->_breaks, jnot);
index ad0dbfdf571c4995430c14ef78018553cd2965da..6b89c9fc14115882365b7539483180dbb331da72 100644 (file)
@@ -161,6 +161,7 @@ int scf_optimize(scf_ast_t* ast, scf_vector_t* functions)
                if (!f->node.define_flag)
                        continue;
 
+               printf("\n");
                scf_logi("------- %s() ------\n", f->node.w->text->data);
 
                scf_basic_block_print_list(&f->basic_block_list_head);
index be31fb6c300cd605fa23bb59f4c3d9be5116987f..15e0c73715cfd6f81a30932d463f79248214de6c 100644 (file)
@@ -156,11 +156,9 @@ int scf_type_cast_check(scf_ast_t* ast, scf_variable_t* dst, scf_variable_t* src
 
                if (scf_type_is_integer(dst->type)) {
 
-                       if (dst->size < src->size) {
-                               scf_logw("type cast %s -> %s discard bits\n",
-                                               src->w->text->data, dst->w->text->data);
-                       }
-
+                       if (dst->size < src->size)
+                               scf_logw("type cast %s -> %s discard bits, file: %s, line: %d\n",
+                                               src->w->text->data, dst->w->text->data, src->w->file->data, src->w->line);
                        return 0;
                }
        }
@@ -178,9 +176,9 @@ failed:
        dst_type = scf_variable_type_name(ast, dst);
        src_type = scf_variable_type_name(ast, src);
 
-       scf_loge("type cast '%s -> %s' with different type: from '%s' to '%s'\n",
+       scf_loge("type cast '%s -> %s' with different type: from '%s' to '%s', file: %s, line: %d\n",
                        src->w->text->data, dst->w->text->data,
-                       src_type->data, dst_type->data);
+                       src_type->data, dst_type->data, src->w->file->data, src->w->line);
 
        scf_string_free(dst_type);
        scf_string_free(src_type);
index 564ab14ccd5ff1dbce67156237c2c4c906d5ed78..7d0360da6e765571a59a0e84a87c9d95ecd29c20 100644 (file)
@@ -128,6 +128,11 @@ static inline int scf_variable_const_string(scf_variable_t* v)
                && 0 == v->nb_dimentions;
 }
 
+static inline int scf_variable_string(scf_variable_t* v)
+{
+       return SCF_VAR_CHAR == v->type && 1 == v->nb_pointers + v->nb_dimentions;
+}
+
 static inline int scf_variable_float(scf_variable_t* v)
 {
        return scf_type_is_float(v->type) && 0 == v->nb_pointers && 0 == v->nb_dimentions;
diff --git a/examples/switch_string.c b/examples/switch_string.c
new file mode 100644 (file)
index 0000000..7c5844a
--- /dev/null
@@ -0,0 +1,20 @@
+int printf(const char* fmt, ...);
+int strcmp(const char* s1, const char* s2);
+
+int main()
+{
+       const char* s = "123";
+
+       switch (s) {
+               case "456":
+                       printf("0\n");
+               case "123":
+                       printf("1\n");
+                       break;
+               default:
+                       printf("default\n");
+                       break;
+       };
+
+       return 0;
+}
index 8ff7f3c56b3c6a6b3a62e4573c344a37058ebe8f..c7d2964fa42a0513a0127a7c3729cb1a526a5bb4 100644 (file)
@@ -250,7 +250,7 @@ static int _x64_function_finish(scf_function_t* f)
                                local += 8;
                }
 
-               scf_logw("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n",
+               scf_logd("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n",
                                local, f->local_vars_size, f->callee_saved_size);
 
                inst = x64_make_inst_I2E(sub, rsp, (uint8_t*)&local, 4);
@@ -1165,6 +1165,7 @@ int scf_x64_select_inst(scf_native_t* ctx, scf_function_t* f)
        for (i = 0; i < local_vars->size; i++) {
                scf_variable_t* v = local_vars->data[i];
                assert(v->w);
+
                scf_logd("v: %p, name: %s_%d_%d, size: %d, bp_offset: %d, arg_flag: %d\n",
                                v, v->w->text->data, v->w->line, v->w->pos,
                                scf_variable_size(v), v->bp_offset, v->arg_flag);
@@ -1194,4 +1195,3 @@ scf_native_ops_t  native_ops_x64 = {
 
        .select_inst     = scf_x64_select_inst,
 };
-
index 0258ced94318d85efedf10132aade6f605ad8a2b..9a7eeb27410d0332066e44c489541698f6bab8b4 100644 (file)
@@ -280,7 +280,7 @@ static int _for_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        d->current_node = fd->parent_node;
 
-       scf_logi("\033[31m for: %d, fd: %p, s->size: %d\033[0m\n", fd->_for->w->line, fd, s->size);
+       scf_logi("for: %d, fd: %p, s->size: %d\n", fd->_for->w->line, fd, s->size);
 
        free(fd);
        fd = NULL;
index cd2f75b3d6ce16904e86980d4204ec41b6e1e629..ad3666e86582f75439a31b55b65ed5bdab31f993 100644 (file)
@@ -195,7 +195,7 @@ static int _if_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        d->current_node = ifd->parent_node;
 
-       scf_logi("\033[31m if: %d, ifd: %p, s->size: %d\033[0m\n", ifd->_if->w->line, ifd, s->size);
+       scf_logi("if: %d, ifd: %p, s->size: %d\n", ifd->_if->w->line, ifd, s->size);
 
        free(ifd);
        ifd = NULL;
index e95de0694eb718d0a883c21dc3d1412608e2f043..fa22c3a29a531a00421045e2afe0b35e4a6c2244 100644 (file)
@@ -30,16 +30,12 @@ static int _switch_action_switch(scf_dfa_t* dfa, scf_vector_t* words, void* data
        scf_stack_t*     s      = d->module_datas[dfa_module_switch.index];
        scf_node_t*     _switch = scf_node_alloc(w, SCF_OP_SWITCH, NULL);
 
-       if (!_switch) {
-               scf_loge("node alloc failed\n");
-               return SCF_DFA_ERROR;
-       }
+       if (!_switch)
+               return -ENOMEM;
 
        dfa_switch_data_t* sd = calloc(1, sizeof(dfa_switch_data_t));
-       if (!sd) {
-               scf_loge("module data alloc failed\n");
-               return SCF_DFA_ERROR;
-       }
+       if (!sd)
+               return -ENOMEM;
 
        if (d->current_node)
                scf_node_add_child(d->current_node, _switch);
@@ -192,7 +188,7 @@ static int _switch_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        d->current_node = sd->parent_node;
 
-       scf_logi("\033[31m switch: %d, sd: %p, s->size: %d\033[0m\n", sd->_switch->w->line, sd, s->size);
+       scf_logi("switch: %d, sd: %p, s->size: %d\n", sd->_switch->w->line, sd, s->size);
 
        free(sd);
        sd = NULL;
index 77aa343b2121be2a27f7bcd1758df8e7b14e8e54..10986188d0d7b896c42a964daf38b14ddb5043a8 100644 (file)
@@ -132,7 +132,7 @@ static int _while_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        d->current_node = wd->parent_node;
 
-       scf_logi("\033[31m while: %d, wd: %p, s->size: %d\033[0m\n", wd->_while->w->line, wd, s->size);
+       scf_logi("while: %d, wd: %p, s->size: %d\n", wd->_while->w->line, wd, s->size);
 
        free(wd);
        wd = NULL;
index 7039425c4817b592bc8cb31e22217ba809d1e6e5..0d53b21e728e3f5649184baf943cda38cb63bf7a 100644 (file)
@@ -40,13 +40,13 @@ static int _scf_expr_calculate_internal(scf_ast_t* ast, scf_node_t* node, void*
                return __scf_op_const_call(ast, (scf_function_t*)node, data);
 
        if (0 == node->nb_nodes) {
+
+               if (scf_type_is_var(node->type) && node->var->w)
+                       scf_logd("w: %s\n", node->var->w->text->data);
+
                assert(scf_type_is_var(node->type)
                                || SCF_LABEL == node->type
                                || node->split_flag);
-
-               if (scf_type_is_var(node->type) && node->var->w) {
-                       scf_logd("w: %s\n", node->var->w->text->data);
-               }
                return 0;
        }
 
@@ -327,30 +327,40 @@ static int _scf_op_const_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes
        scf_handler_data_t* d = data;
        scf_variable_t*     r = NULL;
        scf_expr_t*         e = nodes[0];
+       scf_expr_t*         e2;
+       scf_node_t*         b = nodes[1];
+       scf_node_t*         child;
 
        assert(SCF_OP_EXPR == e->type);
 
        if (_scf_expr_calculate_internal(ast, e, &r) < 0)
                return -1;
 
-       if (_scf_op_const_node(ast, nodes[1], d) < 0)
-               return -1;
+       int i;
+       for (i = 0; i < b->nb_nodes; i++) {
+               child     = b->nodes[i];
+
+               if (SCF_OP_CASE == child->type) {
+                       assert(1    == child->nb_nodes);
+
+                       e = child->nodes[0];
+
+                       assert(SCF_OP_EXPR == e->type);
+
+                       if (_scf_expr_calculate_internal(ast, e, &r) < 0)
+                               return -1;
+
+               } else {
+                       if (_scf_op_const_node(ast, child, d) < 0)
+                               return -1;
+               }
+       }
 
        return 0;
 }
 
 static int _scf_op_const_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
 {
-       assert(1 == nb_nodes);
-
-       scf_handler_data_t* d = data;
-       scf_variable_t*     r = NULL;
-       scf_expr_t*         e = nodes[0];
-
-       assert(SCF_OP_EXPR == e->type);
-
-       if (_scf_expr_calculate_internal(ast, e, &r) < 0)
-               return -1;
        return 0;
 }
 
@@ -453,20 +463,14 @@ static int _scf_op_const_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes,
 {
        assert(1 == nb_nodes);
 
-       scf_handler_data_t* d = data;
-
-       scf_node_t* n      = nodes[0];
        scf_node_t* parent = nodes[0]->parent;
+       scf_node_t* node;
 
-       while (SCF_OP_EXPR == n->type)
-               n = n->nodes[0];
+       scf_expr_simplify(&nodes[0]);
 
-       n->parent->nodes[0] = NULL;
-       scf_node_free(nodes[0]);
-       nodes[0]  = n;
-       n->parent = parent;
+       node = nodes[0];
 
-       int ret = _scf_expr_calculate_internal(ast, n, d);
+       int ret = _scf_expr_calculate_internal(ast, node, data);
        if (ret < 0) {
                scf_loge("\n");
                return -1;
@@ -475,8 +479,7 @@ static int _scf_op_const_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes,
        if (parent->result)
                scf_variable_free(parent->result);
 
-       scf_variable_t* v = _scf_operand_get(n);
-
+       scf_variable_t* v = _scf_operand_get(node);
        if (v)
                parent->result = scf_variable_ref(v);
        else
index 856030faa682dcc5b4c33d6cc0719e5f4511e435..f37493c9ca231ce1c1dd90409dfb7cd0bb4d2ac8 100644 (file)
@@ -1045,7 +1045,6 @@ static int _scf_op_semantic_block(scf_ast_t* ast, scf_node_t** nodes, int nb_nod
                        ret = _scf_op_semantic_node(ast, node, d);
 
                if (ret < 0) {
-                       scf_loge("\n");
                        ast->current_block = up;
                        return -1;
                }
@@ -1285,59 +1284,173 @@ static int _scf_op_semantic_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nod
        return 0;
 }
 
-static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
+static int __switch_for_string(scf_ast_t* ast, scf_node_t* parent, scf_node_t* child, scf_expr_t* e, scf_expr_t* e1, scf_handler_data_t* d)
 {
-       assert(2 == nb_nodes);
-
-       scf_handler_data_t* d = data;
-       scf_variable_t*     r = NULL;
-       scf_expr_t*         e = nodes[0];
+       scf_function_t* f = NULL;
+       scf_expr_t*     e2;
+       scf_expr_t*     e3;
+       scf_expr_t*     e4;
 
-       assert(SCF_OP_EXPR == e->type);
+       int ret = scf_ast_find_function(&f, ast, "strcmp");
+       if (ret < 0)
+               return ret;
 
-       if (_scf_expr_calculate(ast, e, &r) < 0) {
-               scf_loge("\n");
+       if (!f) {
+               scf_loge("can't find function 'strcmp()' for compare const string, file: %s, line: %d\n",
+                               parent->w->file->data, parent->w->line);
                return -1;
        }
 
-       if (!r || !scf_variable_integer(r)) {
-               scf_loge("\n");
-               return -1;
+       e2 = scf_expr_clone(e);
+       if (!e1)
+               return -ENOMEM;
+
+       e3 = scf_expr_alloc();
+       if (!e3) {
+               scf_expr_free(e2);
+               return -ENOMEM;
        }
-       scf_variable_free(r);
-       r = NULL;
 
-       int ret = _scf_op_semantic_node(ast, nodes[1], d);
+       ret = scf_node_add_child(e3, e2);
        if (ret < 0) {
-               scf_loge("\n");
-               return -1;
+               scf_expr_free(e2);
+               scf_expr_free(e3);
+               return ret;
        }
+       e2 = NULL;
 
-       return 0;
+       ret = scf_node_add_child(e3, e1);
+       if (ret < 0) {
+               scf_expr_free(e3);
+               return ret;
+       }
+       child->nodes[0] = NULL;
+
+       e4 = scf_expr_alloc();
+       if (!e4) {
+               scf_expr_free(e3);
+               return -ENOMEM;
+       }
+
+       ret = scf_node_add_child(e4, e3);
+       if (ret < 0) {
+               scf_expr_free(e3);
+               scf_expr_free(e4);
+               return ret;
+       }
+
+       child->nodes[0] = e4;
+       e4->parent      = child;
+
+       d->pret = &e3->result;
+
+       return _semantic_add_call(ast, e3->nodes, e3->nb_nodes, d, f);
 }
 
-static int _scf_op_semantic_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
+static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
 {
-       assert(1 == nb_nodes);
+       assert(2 == nb_nodes);
 
-       scf_handler_data_t* d = data;
-       scf_variable_t*     r = NULL;
-       scf_expr_t*         e = nodes[0];
+       scf_handler_data_t* d      = data;
+       scf_variable_t**    pret   = d->pret;
+       scf_variable_t*     v0     = NULL;
+       scf_variable_t*     v1     = NULL;
+       scf_block_t*        tmp    = ast->current_block;
+       scf_expr_t*         e      = nodes[0];
+       scf_node_t*         b      = nodes[1];
+       scf_node_t*         parent = nodes[0]->parent;
+       scf_node_t*         child;
+       scf_expr_t*         e1;
 
-       assert(SCF_OP_EXPR == e->type);
+       assert(SCF_OP_EXPR  == e->type);
+       assert(SCF_OP_BLOCK == b->type);
 
-       if (_scf_expr_calculate(ast, e, &r) < 0) {
-               scf_loge("\n");
+       if (_scf_expr_calculate(ast, e, &v0) < 0)
                return -1;
-       }
 
-       if (!r || !scf_variable_integer(r)) {
-               scf_loge("\n");
+       if (!scf_variable_integer(v0) && !scf_variable_string(v0)) {
+               scf_loge("result of switch expr should be an integer or string, file: %s, line: %d\n", parent->w->file->data, parent->w->line);
+               scf_variable_free(v0);
                return -1;
        }
-       scf_variable_free(r);
 
+       ast->current_block = (scf_block_t*)b;
+
+       int ret = -1;
+       int i;
+
+       for (i = 0; i < b->nb_nodes; i++) {
+               child     = b->nodes[i];
+
+               if (SCF_OP_CASE == child->type) {
+                       assert(1    == child->nb_nodes);
+
+                       e1 = child->nodes[0];
+
+                       assert(SCF_OP_EXPR == e1->type);
+
+                       ret = _scf_expr_calculate(ast, e1, &v1);
+                       if (ret < 0) {
+                               scf_variable_free(v0);
+                               return ret;
+                       }
+
+                       if (!scf_variable_const_integer(v1) && !scf_variable_const_string(v1)) {
+                               ret = -1;
+                               scf_loge("result of case expr should be const integer or const string, file: %s, line: %d\n", child->w->file->data, child->w->line);
+                               goto error;
+                       }
+
+                       if (!scf_variable_type_like(v0, v1)) {
+
+                               if (scf_type_cast_check(ast, v0, v1) < 0) {
+                                       ret = -1;
+                                       scf_loge("type of switch's expr is NOT same to the case's, file: %s, line: %d\n", child->w->file->data, child->w->line);
+                                       goto error;
+                               }
+
+                               ret = _semantic_add_type_cast(ast, &(e1->nodes[0]), v0, e1->nodes[0]);
+                               if (ret < 0)
+                                       goto error;
+                       }
+
+                       if (scf_variable_const_string(v1)) {
+
+                               ret = __switch_for_string(ast, parent, child, e, e1, d);
+                               if (ret < 0)
+                                       goto error;
+                       }
+
+                       scf_variable_free(v1);
+                       v1 = NULL;
+
+               } else {
+                       ret = _scf_op_semantic_node(ast, child, d);
+                       if (ret < 0) {
+                               scf_variable_free(v0);
+                               return -1;
+                       }
+               }
+       }
+
+       ast->current_block = tmp;
+
+       scf_variable_free(v0);
+
+       d->pret = pret;
        return 0;
+
+error:
+       scf_variable_free(v0);
+       scf_variable_free(v1);
+       d->pret = pret;
+       return ret;
+}
+
+static int _scf_op_semantic_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
+{
+       scf_loge("\n");
+       return -1;
 }
 
 static int _scf_op_semantic_default(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data)
@@ -1404,10 +1517,8 @@ static int __scf_op_semantic_call(scf_ast_t* ast, scf_function_t* f, void* data)
        // change the current block
        ast->current_block = (scf_block_t*)f;
 
-       if (_scf_op_semantic_block(ast, f->node.nodes, f->node.nb_nodes, d) < 0) {
-               scf_loge("\n");
+       if (_scf_op_semantic_block(ast, f->node.nodes, f->node.nb_nodes, d) < 0)
                return -1;
-       }
 
        ast->current_block = tmp;
        return 0;
index e0f889d159240573e96b8f7b7a356d0d33004367..4fbda8e22868f362b18358ea4a7b15949e31611a 100644 (file)
@@ -1860,12 +1860,12 @@ static int _add_debug_sections(scf_parse_t* parse, scf_elf_context_t* elf)
 int scf_parse_compile_functions(scf_parse_t* parse, scf_vector_t* functions)
 {
        scf_function_t* f;
-
        int i;
+
        for (i = 0; i < functions->size; i++) {
                f  =        functions->data[i];
 
-               scf_logi("i: %d, fname: %s, f->argv->size: %d, f->node.define_flag: %d, inline_flag: %d\n",
+               printf("%d, %s(), argv->size: %d, define_flag: %d, inline_flag: %d\n",
                                i, f->node.w->text->data, f->argv->size, f->node.define_flag, f->inline_flag);
 
                if (!f->node.define_flag)