From cc37992b7c4ab800d12f300b434ee5b495dc9ec2 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Sat, 13 Dec 2025 16:11:40 +0800 Subject: [PATCH] 1, js: support 'switch-case', 2, scf: mov source code of _semantic_find_proper_function2() to scf_ast_find_proper_function(). --- examples/js.html | 16 +- js/core/scf_ast.c | 63 +++++++ js/core/scf_ast.h | 3 +- js/core/scf_operator_handler_3ac.c | 16 +- js/core/scf_scope.c | 17 -- js/core/scf_scope.h | 2 - js/core/scf_type_cast.h | 1 - js/doc.c | 18 ++ js/parse/scf_dfa_switch.c | 3 + js/parse/scf_operator_handler_semantic.c | 216 +++++++++++++++-------- js/parse/scf_parse.c | 1 + 11 files changed, 245 insertions(+), 111 deletions(-) diff --git a/examples/js.html b/examples/js.html index 234458c..08e8a76 100644 --- a/examples/js.html +++ b/examples/js.html @@ -8,14 +8,16 @@ diff --git a/js/core/scf_ast.c b/js/core/scf_ast.c index 0b79c91..aa22dff 100644 --- a/js/core/scf_ast.c +++ b/js/core/scf_ast.c @@ -1,4 +1,5 @@ #include"scf_ast.h" +#include"scf_type_cast.h" int scf_ast_open(scf_ast_t** past) { @@ -577,3 +578,65 @@ error: scf_string_free(s); return -1; } + +int scf_ast_find_proper_function(scf_function_t** pf, scf_ast_t* ast, scf_vector_t* fvec, scf_vector_t* argv) +{ + scf_function_t* f; + scf_variable_t* v0; + scf_variable_t* v1; + + int i; + int j; + + for (i = 0; i < fvec->size; ) { + f = fvec->data[i]; + + f->score = 0; + + for (j = 0; j < argv->size; j++) { + v0 = f->argv->data[j]; + v1 = argv->data[j]; + + if (scf_variable_is_struct_pointer(v0)) + continue; + + if (scf_type_cast_check(ast, v0, v1) < 0) + break; + + int type = scf_find_updated_type(ast, v0, v1); + if (type < 0) + break; + + if (scf_variable_nb_pointers(v0) == scf_variable_nb_pointers(v1)) { + if (v0->type == v1->type) + f->score += 10000; + else if (type == v0->type) { + f->score += 1; + + if (type == v1->type) + f->score += 100; + } + } + } + + if (j < argv->size) + assert(0 == scf_vector_del(fvec, f)); // drop invalid function + else + i++; + } + + if (fvec->size <= 0) + return -404; + + int max = INT_MIN; + for (i = 0; i < fvec->size; i++) { + f = fvec->data[i]; + + if (max < f->score) { + max = f->score; + *pf = f; + } + } + + return 0; +} diff --git a/js/core/scf_ast.h b/js/core/scf_ast.h index dbd9169..0cc4cc0 100644 --- a/js/core/scf_ast.h +++ b/js/core/scf_ast.h @@ -82,6 +82,7 @@ static inline scf_scope_t* scf_ast_current_scope(scf_ast_t* ast) return ast->current_block->scope; } +int scf_ast_find_proper_function (scf_function_t** pf, scf_ast_t* ast, scf_vector_t* fvec, scf_vector_t* argv); int scf_ast_find_global_function (scf_function_t** pf, scf_ast_t* ast, char* name); int scf_ast_find_global_variable (scf_variable_t** pv, scf_ast_t* ast, char* name); int scf_ast_find_global_type (scf_type_t** pt, scf_ast_t* ast, char* name); @@ -92,8 +93,6 @@ int scf_ast_find_variable (scf_variable_t** pv, scf_ast_t* ast, char* name); int scf_ast_find_type (scf_type_t** pt, scf_ast_t* ast, char* name); int scf_ast_find_type_type(scf_type_t** pt, scf_ast_t* ast, int type); -int scf_operator_function_call(scf_ast_t* ast, scf_function_t* f, const int argc, const scf_variable_t** argv, scf_variable_t** pret, scf_list_t* _3ac_list_head); - int scf_ast_open(scf_ast_t** past); int scf_ast_close(scf_ast_t* ast); diff --git a/js/core/scf_operator_handler_3ac.c b/js/core/scf_operator_handler_3ac.c index 3d31a07..02b34ad 100644 --- a/js/core/scf_operator_handler_3ac.c +++ b/js/core/scf_operator_handler_3ac.c @@ -1211,12 +1211,20 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void scf_node_t* srcs[2] = {e, e2}; - if (SCF_OP_CALL != e2->type) - cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2); - else + if (SCF_OP_CALL == e2->type) { cmp = scf_3ac_code_NN(SCF_OP_3AC_TEQ, NULL, 0, &e2, 1); - jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL); + scf_variable_t* v = _scf_operand_get(e2->nodes[0]); + scf_function_t* f = v->func_ptr; + + if (SCF_OP_EQ == f->op_type) + jnot = scf_3ac_jmp_code(SCF_OP_3AC_JZ, NULL, NULL); + else + jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL); + } else { + 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); diff --git a/js/core/scf_scope.c b/js/core/scf_scope.c index 9e7612f..424fb0f 100644 --- a/js/core/scf_scope.c +++ b/js/core/scf_scope.c @@ -181,23 +181,6 @@ scf_function_t* scf_scope_find_same_function(scf_scope_t* scope, scf_function_t* return NULL; } -scf_function_t* scf_scope_find_proper_function(scf_scope_t* scope, const char* name, scf_vector_t* argv) -{ - scf_function_t* f; - scf_list_t* l; - - for (l = scf_list_head(&scope->function_list_head); l != scf_list_sentinel(&scope->function_list_head); l = scf_list_next(l)) { - f = scf_list_data(l, scf_function_t, list); - - if (strcmp(f->node.w->text->data, name)) - continue; - - if (scf_function_same_argv(f->argv, argv)) - return f; - } - return NULL; -} - int scf_scope_find_like_functions(scf_vector_t** pfunctions, scf_scope_t* scope, const char* name, scf_vector_t* argv) { scf_function_t* f; diff --git a/js/core/scf_scope.h b/js/core/scf_scope.h index 119077d..53ef96a 100644 --- a/js/core/scf_scope.h +++ b/js/core/scf_scope.h @@ -40,8 +40,6 @@ scf_function_t* scf_scope_find_function(scf_scope_t* scope, const char* name); scf_function_t* scf_scope_find_same_function(scf_scope_t* scope, scf_function_t* f0); -scf_function_t* scf_scope_find_proper_function(scf_scope_t* scope, const char* name, scf_vector_t* argv); - int scf_scope_find_overloaded_functions(scf_vector_t** pfunctions, scf_scope_t* scope, const int op_type, scf_vector_t* argv); int scf_scope_find_like_functions(scf_vector_t** pfunctions, scf_scope_t* scope, const char* name, scf_vector_t* argv); diff --git a/js/core/scf_type_cast.h b/js/core/scf_type_cast.h index 4ea173b..1e89778 100644 --- a/js/core/scf_type_cast.h +++ b/js/core/scf_type_cast.h @@ -36,4 +36,3 @@ int scf_cast_to_float(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src int scf_cast_to_double(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src); #endif - diff --git a/js/doc.c b/js/doc.c index 6de9ccf..ceeda44 100644 --- a/js/doc.c +++ b/js/doc.c @@ -412,6 +412,24 @@ struct Object return res; } + bool operator==(Object* this, double d) + { + printf("this->d: %lg, d: %lg\n", this->d, d); + if (JS_Number == this->type) + return this->d == d; + + if (JS_Boolean == this->type) + return this->i64 == d; + return 0; + } + + bool operator==(Object* this, const char* s) + { + if (JS_String == this->type) + return !strcmp(this->str, s); + return 0; + } + bool operator==(Object* this, Object* that) { if (JS_Number == this->type && JS_Number == that->type) diff --git a/js/parse/scf_dfa_switch.c b/js/parse/scf_dfa_switch.c index 331236a..084a883 100644 --- a/js/parse/scf_dfa_switch.c +++ b/js/parse/scf_dfa_switch.c @@ -269,6 +269,9 @@ static int _dfa_init_syntax_switch(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, expr, entry, expr); SCF_DFA_GET_MODULE_NODE(dfa, block, entry, block); + // switch start + scf_vector_add(dfa->syntaxes, _switch); + scf_dfa_node_add_child(_switch, lp); scf_dfa_node_add_child(lp, expr); scf_dfa_node_add_child(expr, rp); diff --git a/js/parse/scf_operator_handler_semantic.c b/js/parse/scf_operator_handler_semantic.c index 22bb5fe..f3eacb6 100644 --- a/js/parse/scf_operator_handler_semantic.c +++ b/js/parse/scf_operator_handler_semantic.c @@ -284,75 +284,15 @@ static int _semantic_add_call(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, return _semantic_add_call_rets(ast, parent, d, f); } -static int _semantic_find_proper_function2(scf_ast_t* ast, scf_vector_t* fvec, scf_vector_t* argv, scf_function_t** pf) -{ - scf_function_t* f; - scf_variable_t* v0; - scf_variable_t* v1; - - int i; - int j; - - for (i = 0; i < fvec->size; ) { - f = fvec->data[i]; - - f->score = 0; - - for (j = 0; j < argv->size; j++) { - v0 = f->argv->data[j]; - v1 = argv->data[j]; - - if (scf_variable_is_struct_pointer(v0)) - continue; - - if (scf_type_cast_check(ast, v0, v1) < 0) - break; - - int type = scf_find_updated_type(ast, v0, v1); - if (type < 0) - break; - - if (scf_variable_nb_pointers(v0) == scf_variable_nb_pointers(v1)) { - if (type == v0->type) { - f->score += 1; - - if (type == v1->type) - f->score += 1000; - } - } - } - - if (j < argv->size) - assert(0 == scf_vector_del(fvec, f)); // drop invalid function - else - i++; - } - - if (fvec->size <= 0) - return -404; - - int max = INT_MIN; - for (i = 0; i < fvec->size; i++) { - f = fvec->data[i]; - - if (max < f->score) { - max = f->score; - *pf = f; - } - } - - return 0; -} - static int _semantic_find_proper_function(scf_ast_t* ast, scf_type_t* t, const char* fname, scf_vector_t* argv, scf_function_t** pf) { scf_vector_t* fvec = NULL; - int ret = scf_scope_find_like_functions(&fvec, t->scope, fname, argv); + int ret = scf_scope_find_like_functions(&fvec, t->scope, fname, argv); if (ret < 0) return ret; - ret = _semantic_find_proper_function2(ast, fvec, argv, pf); + ret = scf_ast_find_proper_function(pf, ast, fvec, argv); scf_vector_free(fvec); return ret; @@ -427,7 +367,7 @@ static int _semantic_do_overloaded(scf_ast_t* ast, scf_node_t** nodes, int nb_no return ret; } - ret = _semantic_find_proper_function2(ast, fvec, argv, &f); + ret = scf_ast_find_proper_function(&f, ast, fvec, argv); if (ret < 0) scf_loge("\n"); else @@ -488,7 +428,7 @@ static int _semantic_do_overloaded_assign(scf_ast_t* ast, scf_node_t** nodes, in return ret; } - ret = _semantic_find_proper_function2(ast, fvec, argv, &f); + ret = scf_ast_find_proper_function(&f, ast, fvec, argv); if (ret < 0) scf_loge("\n"); else @@ -1327,6 +1267,117 @@ static int _scf_op_semantic_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nod return 0; } +static int __switch_for_Object(scf_ast_t* ast, scf_type_t* Object, scf_node_t* parent, scf_node_t* child, scf_expr_t* e, scf_expr_t* e1, scf_handler_data_t* d, + scf_variable_t* v, + scf_variable_t* v1) +{ + scf_function_t* f = NULL; + scf_vector_t* fvec = NULL; + scf_vector_t* argv; + scf_expr_t* e2; + scf_expr_t* e3; + scf_expr_t* e4; + + argv = scf_vector_alloc(); + if (!argv) + return -ENOMEM; + + int ret = scf_vector_add(argv, v); + if (ret < 0) { + scf_vector_free(argv); + return ret; + } + + ret = scf_vector_add(argv, v1); + if (ret < 0) { + scf_vector_free(argv); + return ret; + } + + ret = scf_scope_find_overloaded_functions(&fvec, Object->scope, SCF_OP_EQ, argv); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = scf_ast_find_proper_function(&f, ast, fvec, argv); + if (ret < 0) { + scf_loge("can't find overloaded operator '==' for compare Object, file: %s, line: %d\n", + parent->w->file->data, parent->w->line); + return -1; + } + + scf_vector_free(argv); + scf_vector_free(fvec); + argv = NULL; + fvec = NULL; + + assert(2 == f->argv->size); + + if (!scf_variable_same_type(f->argv->data[1], v1)) { + e2 = e1; + while (SCF_OP_EXPR == e2->type) + e2 = e2->nodes[0]; + + ret = _semantic_add_type_cast(ast, &(e2->parent->nodes[0]), f->argv->data[1], e2); + if (ret < 0) + return ret; + } + + e2 = scf_expr_clone(e); + if (!e1) + return -ENOMEM; + + v = NULL; + if (_scf_expr_calculate(ast, e2, &v) < 0) { + scf_expr_free(e2); + return -1; + } + scf_variable_free(v); + v = NULL; + + e3 = scf_expr_alloc(); + if (!e3) { + scf_expr_free(e2); + return -ENOMEM; + } + + ret = scf_node_add_child(e3, e2); + if (ret < 0) { + scf_expr_free(e2); + scf_expr_free(e3); + return ret; + } + e2 = NULL; + + 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 __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) { scf_function_t* f = NULL; @@ -1407,6 +1458,7 @@ static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_no scf_variable_t* v0 = NULL; scf_variable_t* v1 = NULL; scf_block_t* tmp = ast->current_block; + scf_type_t* Object = NULL; scf_expr_t* e = nodes[0]; scf_node_t* b = nodes[1]; scf_node_t* parent = nodes[0]->parent; @@ -1416,6 +1468,9 @@ static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_no assert(SCF_OP_EXPR == e->type); assert(SCF_OP_BLOCK == b->type); + if (scf_ast_find_type(&Object, ast, "Object") < 0) + return -1; + if (_scf_expr_calculate(ast, e, &v0) < 0) return -1; @@ -1452,24 +1507,29 @@ static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_no 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 (v0->type == Object->type) { + ret = __switch_for_Object(ast, Object, parent, child, e, e1, d, v0, v1); if (ret < 0) goto error; - } - if (scf_variable_const_string(v1)) { + } else { + 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 = __switch_for_string(ast, parent, child, e, e1, d); - if (ret < 0) - 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); diff --git a/js/parse/scf_parse.c b/js/parse/scf_parse.c index 5d180b8..852afbd 100644 --- a/js/parse/scf_parse.c +++ b/js/parse/scf_parse.c @@ -2334,6 +2334,7 @@ int scf_parse_compile(scf_parse_t* parse, const char* arch) switch (e->type) { case SCF_OP_EXPR: + case SCF_OP_SWITCH: case SCF_OP_IF: case SCF_OP_FOR: ret = scf_node_add_child((scf_node_t*)f, e); -- 2.25.1