diff options
author | kdx <kikoodx@paranoici.org> | 2023-06-10 00:42:25 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-06-10 00:42:25 +0200 |
commit | afb74639ece6a01b4ddbe1740466083c7263241a (patch) | |
tree | a992cdda520b234d0b1827809fe18bfdd54e049e | |
parent | b8decd2179c0fa6b15ffaa9f9929b8e0de6252fd (diff) | |
download | golem-afb74639ece6a01b4ddbe1740466083c7263241a.tar.gz |
function call
-rw-r--r-- | Tupfile | 2 | ||||
-rw-r--r-- | src/main.c | 79 | ||||
-rwxr-xr-x | testing.sh | 3 |
3 files changed, 77 insertions, 7 deletions
@@ -1,6 +1,6 @@ CC = gcc LD = $(CC) -CFLAGS = -std=c99 -Wall -Wextra +CFLAGS = -O0 -g3 -std=c99 -Wall -Wextra LIBS = NAME = golem @@ -44,7 +44,7 @@ static void expect(const Token *tok, TokenType type) { if (tok->type != type) - error("expected a %s", str_tok[type]); + error("expected a %s, got %s", str_tok[type], str_tok[tok->type]); } static bool @@ -149,8 +149,10 @@ typedef enum { NOD_LE, // <= NOD_NUM, // integer NOD_EXPR_STMT, + NOD_RETURN_STMT, NOD_FUN, NOD_WORD, + NOD_FNCALL, } NodeType; typedef struct Node Node; @@ -212,6 +214,7 @@ static Node *stmt(Token **rest, Token *tok); static Node *function(Token **rest, Token *tok); static Node *expr(Token **rest, Token *tok); static Node *expr_stmt(Token **rest, Token *tok); +static Node *return_stmt(Token **rest, Token *tok); static Node *equality(Token **rest, Token *tok); static Node *relational(Token **rest, Token *tok); static Node *add(Token **rest, Token *tok); @@ -366,6 +369,29 @@ primary(Token **rest, Token *tok) return node; } + if (tok->type == TOK_WORD) { + /* function call */ + Node *node = new_word(tok); + tok = tok->next; + node->type = NOD_FNCALL; + + /* args */ + Node head = {0}; + Node *cur = &head; + + tok = skip(tok, "("); + while (tok->type != TOK_EOF && !equal(tok, ")")) { + cur = cur->next = expr(&tok, tok); + if (equal(tok, ",")) + tok = tok->next; + } + *rest = skip(tok, ")"); + + node->rhs = head.next; + return node; + } + + printf("'%.*s'\n", tok->len, tok->loc); error("expected an expression"); return NULL; } @@ -373,6 +399,8 @@ primary(Token **rest, Token *tok) static Node * stmt(Token **rest, Token *tok) { + if (equal(tok, "return")) + return return_stmt(rest, tok); return expr_stmt(rest, tok); } @@ -384,10 +412,22 @@ static Node return node; } +static Node +*return_stmt(Token **rest, Token *tok) +{ + tok = skip(tok, "return"); + Node *const node = new_unary(NOD_RETURN_STMT, expr(&tok, tok)); + *rest = skip(tok, ";"); + return node; +} + // code generator static int depth; +static void gen_expr(Node *node); +static void gen_fncall(Node *node); + static void gen_expr(Node *node) { @@ -397,6 +437,11 @@ gen_expr(Node *node) return; } + if (node->type == NOD_FNCALL) { + gen_fncall(node); + return; + } + gen_expr(node->lhs); gen_expr(node->rhs); @@ -434,16 +479,39 @@ gen_expr(Node *node) } static void +gen_fncall(Node *node) +{ + printf("\t( function call )\n"); + Node *cur = node->rhs; + while (cur != NULL) { + gen_expr(cur); + depth -= 1; + cur = cur->next; + } + printf("\tJRT ,__fn_%.*s\n", node->len, node->loc); + depth += 1; +} + +static void gen_function(Node *node) { - printf("@_fn_%.*s\n", node->lhs->len, node->lhs->loc); + printf("@__fn_%.*s\n", node->lhs->len, node->lhs->loc); node = node->rhs; while (node != NULL) { - gen_expr(node->lhs); - while (depth) { + switch (node->type) { + case NOD_EXPR_STMT: + gen_expr(node->lhs); printf("\tPOP ( discard stack )\n"); depth -= 1; + break; + case NOD_RETURN_STMT: + gen_expr(node->lhs); + printf("\tRET\n"); + depth -= 1; + break; + default: + error("unexpected %d", node->type); } node = node->next; } @@ -481,8 +549,9 @@ main(int argc, char **argv) Node *node = parse(tok); - printf("\tJMP ,_fn_main ( entry point )\n"); + printf("\tJMP ,__fn_main ( entry point )\n"); codegen(node); + printf("@__stack\n"); assert(depth == 0); return 0; @@ -11,7 +11,8 @@ function test() { } tup || exit 1 -test "main(){5 + 2;}" +test "main(){5 + 2; return 4;}" test "main(){6 + 3;}" test "main(){'a' - 'b';}" +test "main() { fizz(50 + buzz() - 3) * 4; } fizz(x) { return 3; } buzz() { return 42; }" rm -f build/tmp.* |