aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorc2024-03-30 09:24:53 -0400
committerc2024-03-30 09:24:53 -0400
commitc26c65dcf836a86ff3374a3e92e57ec61568e8c9 (patch)
tree0673c1beb44eddf26e7ff23f096ded05c0ddbc9c /src
parentbbcda663d5b2b2f055de12107e0abab536e5beea (diff)
Nested functions and transitivity works.
Added a `str_cat` function.
Diffstat (limited to 'src')
-rw-r--r--src/doer.c76
-rw-r--r--src/include/doer.h17
2 files changed, 69 insertions, 24 deletions
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" },