From: nishi Date: Sun, 5 May 2024 16:17:27 +0000 (+0000) Subject: cond works X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=74849fb31d1d1e3ba797cd4c48c477d12d023748;p=serenade.git cond works git-svn-id: file:///raid/svn-main/nishi-serenade/trunk@109 0f02c867-ac3d-714e-8a88-971ba1f6efcf --- diff --git a/Serenade/interpreter.c b/Serenade/interpreter.c index 8908887..60faa41 100644 --- a/Serenade/interpreter.c +++ b/Serenade/interpreter.c @@ -71,6 +71,29 @@ struct sn_generic* math_handler(struct sn_interpreter* sn, int args, struct sn_g return gen; } +struct sn_generic* cond_handler(struct sn_interpreter* sn, int args, struct sn_generic** gens) { + struct sn_generic* gen = malloc(sizeof(struct sn_generic)); + gen->type = SN_TYPE_DOUBLE; + gen->number = 0; + int i; + if(args != 3 || !(gens[1]->type == SN_TYPE_DOUBLE && gens[2]->type == SN_TYPE_DOUBLE)) { + gen->number = -1; + } else { + double a = gens[1]->number; + double b = gens[2]->number; + if(strcmp(gens[0]->name, "<") == 0) { + gen->number = a < b ? 1 : 0; + } else if(strcmp(gens[0]->name, ">") == 0) { + gen->number = a > b ? 1 : 0; + } else if(strcmp(gens[0]->name, ">=") == 0) { + gen->number = a >= b ? 1 : 0; + } else if(strcmp(gens[0]->name, ">=") == 0) { + gen->number = a <= b ? 1 : 0; + } + } + return gen; +} + struct sn_generic* print_handler(struct sn_interpreter* sn, int args, struct sn_generic** gens) { struct sn_generic* gen = malloc(sizeof(struct sn_generic)); int i; @@ -151,6 +174,10 @@ void sn_stdlib_init(struct sn_interpreter* sn) { sn_set_handler(sn, "-", math_handler); sn_set_handler(sn, "*", math_handler); sn_set_handler(sn, "/", math_handler); + sn_set_handler(sn, "<=", cond_handler); + sn_set_handler(sn, ">=", cond_handler); + sn_set_handler(sn, "<", cond_handler); + sn_set_handler(sn, ">", cond_handler); sn_set_handler(sn, "print", print_handler); sn_set_handler(sn, "eval", eval_handler); sn_set_handler(sn, "define-variable", defvar_handler); @@ -199,8 +226,10 @@ do_again: int j; do_again2: for(j = 0; sn->generics[i][j] != NULL; j++) { - if(sn->generics[i][j] != (void*)1) sn_generic_free(sn, sn->generics[i][j]); - goto do_again2; + if(sn->generics[i][j] != (void*)1 && sn->generics[i][j] != (void*)2) { + sn_generic_free(sn, sn->generics[i][j]); + goto do_again2; + } } free(sn->generics[i]); } @@ -306,6 +335,7 @@ int sn_eval(struct sn_interpreter* sn, char* data, unsigned long long len) { } } } + if(r == 1) return r; int j; struct sn_generic*** oldgens = sn->generics; for(j = 0; oldgens[j] != NULL; j++) diff --git a/Serenade/run.c b/Serenade/run.c index fc27efb..670a508 100644 --- a/Serenade/run.c +++ b/Serenade/run.c @@ -104,7 +104,47 @@ struct sn_generic* _sn_run(struct sn_interpreter* sn, struct sn_generic* gen) { free(name); return r; } else if(strcmp(op->name, "loop") == 0) { + int i; + for(i = 0; gen->tree->args[i] != NULL; i++) + ; + if(i < 2) { + fprintf(stderr, "Insufficient arguments\n"); + free(r); + return NULL; + } + do_loop:; + struct sn_interpreter_kv** old_kv = sn->local_variables; + sn->local_variables = malloc(sizeof(struct sn_interpreter_kv*)); + sn->local_variables[0] = NULL; + + struct sn_generic* cond = _sn_run(sn, gen->tree->args[1]); + if(cond == NULL) { + free(r); + return NULL; + } + + free(sn->local_variables); + sn->local_variables = old_kv; + r->type = SN_TYPE_VOID; + + if(cond->type != SN_TYPE_DOUBLE) { + fprintf(stderr, "Cannot use non-number (Type %d) for loop condition\n", r->type); + free(r); + return NULL; + } else if(cond->number != 0) { + old_kv = sn->local_variables; + sn->local_variables = malloc(sizeof(struct sn_interpreter_kv*)); + sn->local_variables[0] = NULL; + + for(i = 2; gen->tree->args[i] != NULL; i++) { + _sn_run(sn, gen->tree->args[i]); + } + + free(sn->local_variables); + sn->local_variables = old_kv; + goto do_loop; + } return r; } bool called = false; @@ -115,6 +155,11 @@ struct sn_generic* _sn_run(struct sn_interpreter* sn, struct sn_generic* gen) { int argc = j; for(j = 0; gen->tree->args[j]; j++) { args[j] = _sn_run(sn, gen->tree->args[j]); + if(args[j] == NULL) { + free(args); + free(r); + return NULL; + } } if(0) { free(r); diff --git a/Serenade/util.c b/Serenade/util.c index a9ff8ba..55693de 100644 --- a/Serenade/util.c +++ b/Serenade/util.c @@ -62,6 +62,8 @@ void sn_print_to(FILE* f, struct sn_generic* gen) { fprintf(f, ":%x", gen->handler); } fprintf(f, ">"); + } else if(gen->type == SN_TYPE_VARIABLE) { + fprintf(f, "", gen->name == NULL ? "(unnamed)" : gen->name); } else if(gen->type == SN_TYPE_PTR) { fprintf(f, "", gen->ptr); }