summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-10 00:42:25 +0200
committerkdx <kikoodx@paranoici.org>2023-06-10 00:42:25 +0200
commitafb74639ece6a01b4ddbe1740466083c7263241a (patch)
treea992cdda520b234d0b1827809fe18bfdd54e049e
parentb8decd2179c0fa6b15ffaa9f9929b8e0de6252fd (diff)
downloadgolem-afb74639ece6a01b4ddbe1740466083c7263241a.tar.gz
function call
-rw-r--r--Tupfile2
-rw-r--r--src/main.c79
-rwxr-xr-xtesting.sh3
3 files changed, 77 insertions, 7 deletions
diff --git a/Tupfile b/Tupfile
index 4b55aec..d01672e 100644
--- a/Tupfile
+++ b/Tupfile
@@ -1,6 +1,6 @@
CC = gcc
LD = $(CC)
-CFLAGS = -std=c99 -Wall -Wextra
+CFLAGS = -O0 -g3 -std=c99 -Wall -Wextra
LIBS =
NAME = golem
diff --git a/src/main.c b/src/main.c
index afc74dc..dbe70c0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/testing.sh b/testing.sh
index f6f0083..40f93c2 100755
--- a/testing.sh
+++ b/testing.sh
@@ -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.*