From c26c65dcf836a86ff3374a3e92e57ec61568e8c9 Mon Sep 17 00:00:00 2001 From: c Date: Sat, 30 Mar 2024 09:24:53 -0400 Subject: Nested functions and transitivity works. Added a `str_cat` function. --- src/doer.c | 76 ++++++++++++++++++++++++++++++++++++++++++------------ src/include/doer.h | 17 +++++++----- 2 files changed, 69 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/doer.c b/src/doer.c index 19de0d8..2968882 100644 --- a/src/doer.c +++ b/src/doer.c @@ -74,7 +74,8 @@ char* doer_eval_str(doer_t* doer) { switch (doer->tree->type) { case TREE_TYPE_CALL: - doer->tree = doer_find_target_from_call(doer->targets, doer->tree); + // doer->tree = doer_find_target_from_call(doer->targets, doer->tree); + doer->tree = doer_do_call(doer); return doer_eval_str(doer); case TREE_TYPE_DEF: doer->tree = doer->tree->data.def.val; @@ -87,38 +88,68 @@ char* doer_eval_str(doer_t* doer) { } } -void blin_die(doer_t* doer) { +tree_t* blin_die(doer_t* doer) { exit(1); + return NULL; // Doesn't really matter what happens here. } -void blin_print(doer_t* doer) { +tree_t* blin_print(doer_t* doer) { doer->tree = doer->tree->data.call.arg->data.carg.val; + char* strval = doer_eval_str(doer); printf( "%s", - doer_eval_str(doer) + strval ); + + tree_t* lstr = tree_init(TREE_TYPE_LSTR, doer->tree->parent); + lstr->data.lstr.val = strval; + lstr->data.lstr.len = strlen(strval); + + return lstr; } -void blin_printl(doer_t* doer) { +tree_t* blin_printl(doer_t* doer) { doer->tree = doer->tree->data.call.arg->data.carg.val; + char* strval = doer_eval_str(doer); printf( "%s\n", - doer_eval_str(doer) + strval ); + + tree_t* lstr = tree_init(TREE_TYPE_LSTR, doer->tree->parent); + lstr->data.lstr.val = strval; + lstr->data.lstr.len = strlen(strval); + + return doer->tree; } -void blin_str_cat(doer_t* doer) { +tree_t* blin_str_cat(doer_t* doer) { tree_t* oldt = doer->tree; doer->tree = doer->tree->data.call.arg->data.carg.val; char* str1 = doer_eval_str(doer); doer->tree = oldt->data.call.arg->data.carg.nxt->data.carg.val; char* str2 = doer_eval_str(doer); - tree_destroy(doer->tree); + char* val = emalloc( + sizeof(str1) + + sizeof(str2) - + sizeof(char) + ); + + strcpy(val, str1); + strcat(val, str2); + + free(str1); + free(str2); -// doer->tree = tree_init(TREE_TYPE_LSTR); + doer->tree = tree_init(TREE_TYPE_LSTR, oldt->parent); + + doer->tree->data.lstr.val = val; + doer->tree->data.lstr.len = strlen(val); + + return doer->tree; } void doer_do_block(doer_t* doer) { @@ -146,27 +177,38 @@ void doer_do_expr(doer_t* doer) { } void doer_do_def(doer_t* doer) { + tree_t* tag2 = doer->tree->data.def.tag->data.tag.nxt; target_t* target = target_init( - doer->tree-> // HACK: Grab the 2nd tag's value (w/o checking if - // it's actually there…). - data.def.tag-> - data.tag.nxt-> - data.tag.val, + tag2->data.tag.val, // HACK: Grab the 2nd tag's value, without + // checking if it's actually there… doer->tree ); doer_add_target(doer, target); } -void doer_do_call(doer_t* doer) { +tree_t* doer_do_call(doer_t* doer) { + tree_t* blin = doer_do_call_blin(doer); + if (!blin) return doer_find_target_from_call(doer->targets, doer->tree); + else return blin; +} + +tree_t* doer_do_call_blin(doer_t* doer) { // Search through built-in functions first. for (int i = 0; i < sizeof(blinfs) / sizeof(blinf_t); i++) { if (!strcmp(blinfs[i].name, doer->tree->data.call.target)) { - (blinfs[i].fp)(doer); - return; + return (blinfs[i].fp)(doer); } } // Search through targets next. LOG_DBGF("got %s", doer->ltarget->tree->data.def.tag->data.tag.nxt->data.tag.val); + + return NULL; } + +// TODO: doer_do_call will check first doer_do_call_blin and then +// doer_do_call_def for user-defined functions. Will return a tree, which will +// replace the call in the tree. +// +// Maybe the parent should be set by the looping function? diff --git a/src/include/doer.h b/src/include/doer.h index 2bdad56..b1c8e64 100644 --- a/src/include/doer.h +++ b/src/include/doer.h @@ -40,7 +40,7 @@ void doer_destroy(doer_t* doer); /* Built-in function. */ typedef struct BLINF { - void (*fp)(doer_t*); // The callback function in C. + tree_t* (*fp)(doer_t*); // The callback function in C. tree_type_t returnt; // The return type of the function. tree_type_t* argts; // Array of the arguments' types. char name[24]; @@ -56,26 +56,29 @@ char* doer_eval_str(doer_t* doer); // `die`: dies. Does not accept any arguments, returns int (if a tree falls in // the forest, but it burns down before anyone can hear it, did it ever make a // sound at all?) TODO: Make this actually clean up afterwards. -void blin_die(doer_t* doer); +tree_t* blin_die(doer_t* doer); // `print`: print a string. -void blin_print(doer_t* doer); +tree_t* blin_print(doer_t* doer); static tree_type_t blin_print_args[] = { TREE_TYPE_LSTR }; // `printl`: print a string, and add a newline. -void blin_printl(doer_t* doer); +tree_t* blin_printl(doer_t* doer); static tree_type_t blin_printl_args[] = { TREE_TYPE_LSTR }; // `str_cat`: concatenate strings. -void blin_str_cat(doer_t* doer); +// Returns a tree pointer to a lstr. +tree_t* blin_str_cat(doer_t* doer); static tree_type_t blin_str_cat_args[] = { TREE_TYPE_LSTR, TREE_TYPE_LSTR }; +tree_t* doer_do_call(doer_t* doer); +tree_t* doer_do_call_blin(doer_t* doer); +tree_t* doer_do_call_def(doer_t* doer); +tree_t* doer_do_carg(doer_t* doer); void doer_do_block(doer_t* tree); void doer_do_expr(doer_t* tree); void doer_do_lint(doer_t* tree); void doer_do_lstr(doer_t* tree); void doer_do_tag(doer_t* tree); void doer_do_darg(doer_t* tree); -void doer_do_carg(doer_t* tree); void doer_do_def(doer_t* tree); -void doer_do_call(doer_t* tree); static blinf_t blinfs[] = { { blin_die, TREE_TYPE_LINT, NULL, "die" }, -- cgit v1.2.3