diff options
author | kdx <kikoodx@paranoici.org> | 2023-06-10 01:30:17 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-06-10 01:30:17 +0200 |
commit | db48a58769ac267a8de49f456cb4e5b27bfddb40 (patch) | |
tree | b42796d9b04049296d451c458adb4105facaf17e | |
parent | 0e5b99fbbb46d5e91feca6f6f862f11359b92aa7 (diff) | |
download | golem-db48a58769ac267a8de49f456cb4e5b27bfddb40.tar.gz |
global assign
-rw-r--r-- | src/main.c | 92 | ||||
-rwxr-xr-x | testing.sh | 19 |
2 files changed, 98 insertions, 13 deletions
@@ -44,7 +44,8 @@ static void expect(const Token *tok, TokenType type) { if (tok->type != type) - error("expected a %s, got %s", str_tok[type], str_tok[tok->type]); + error("expected a %s, got %s '%.*s'", + str_tok[type], str_tok[tok->type], tok->len, tok->loc); } static bool @@ -86,7 +87,7 @@ is_punct(const char *p) if (strchr("=!<>", p[0]) != NULL && p[1] == '=') return 2; - return (strchr("+-/*()<>,;{}", p[0]) != NULL); + return (strchr("+-/*()<>,;{}=", p[0]) != NULL); } static Token * @@ -131,7 +132,7 @@ tokenize(char *p) continue; } - error("invalid token"); + error("invalid token '%c'", *p); } cur->next = new_token(TOK_EOF, p, p); @@ -150,9 +151,11 @@ typedef enum { NOD_NUM, // integer NOD_EXPR_STMT, NOD_RETURN_STMT, + NOD_ASSIGN_STMT, NOD_FUN, NOD_WORD, NOD_FNCALL, + NOD_GLOBAL, } NodeType; typedef struct Node Node; @@ -212,9 +215,11 @@ new_num(int val) static Node *stmt(Token **rest, Token *tok); static Node *function(Token **rest, Token *tok); +static Node *global(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 *assign_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); @@ -253,6 +258,24 @@ function(Token **rest, Token *tok) } static Node * +global(Token **rest, Token *tok) +{ + tok = skip(tok, "global"); + Node *const node = new_word(tok); + node->type = NOD_GLOBAL; + + tok = tok->next; + if (equal(tok, "=")) { + tok = tok->next; + node->val = get_number(tok); + tok = tok->next; + } + + *rest = skip(tok, ";"); + return node; +} + +static Node * expr(Token **rest, Token *tok) { return equality(rest, tok); @@ -369,7 +392,7 @@ primary(Token **rest, Token *tok) return node; } - if (tok->type == TOK_WORD) { + if (tok->type == TOK_WORD && equal(tok->next, "(")) { /* function call */ Node *node = new_word(tok); tok = tok->next; @@ -391,6 +414,13 @@ primary(Token **rest, Token *tok) return node; } + if (tok->type == TOK_WORD) { + /* variable */ + Node *node = new_word(tok); + *rest = tok->next; + return node; + } + printf("'%.*s'\n", tok->len, tok->loc); error("expected an expression"); return NULL; @@ -401,6 +431,8 @@ stmt(Token **rest, Token *tok) { if (equal(tok, "return")) return return_stmt(rest, tok); + if (equal(tok->next, "=")) + return assign_stmt(rest, tok); return expr_stmt(rest, tok); } @@ -421,12 +453,25 @@ static Node return node; } +static Node +*assign_stmt(Token **rest, Token *tok) +{ + expect(tok, TOK_WORD); + skip(tok->next, "="); + Node *const word = new_word(tok); + Node *const node = new_binary(NOD_ASSIGN_STMT, word, expr(&tok, tok->next->next)); + *rest = skip(tok, ";"); + return node; +} + // code generator static int depth; static void gen_expr(Node *node); +static void gen_globaldec(Node *node); static void gen_fncall(Node *node); +static void gen_globalget(Node *node); static void gen_expr(Node *node) @@ -442,6 +487,11 @@ gen_expr(Node *node) return; } + if (node->type == NOD_WORD) { + gen_globalget(node); + return; + } + gen_expr(node->lhs); gen_expr(node->rhs); @@ -479,6 +529,13 @@ gen_expr(Node *node) } static void +gen_globaldec(Node *node) +{ + printf("@__gl_%.*s\n", node->len, node->loc); + printf("\tLIT %04d\n", node->val); +} + +static void gen_fncall(Node *node) { Node *cur = node->rhs; @@ -492,6 +549,14 @@ gen_fncall(Node *node) } static void +gen_globalget(Node *node) +{ + printf("\tLIT ,__gl_%.*s\n", node->len, node->loc); + printf("\tLDA\n"); + depth += 1; +} + +static void gen_function(Node *node) { printf("@__fn_%.*s\n", node->lhs->len, node->lhs->loc); @@ -509,6 +574,12 @@ gen_function(Node *node) printf("\tRET\n"); depth -= 1; break; + case NOD_ASSIGN_STMT: + gen_expr(node->rhs); + printf("\tLIT ,__gl_%.*s\n\tSTA\n", + node->lhs->len, node->lhs->loc); + depth -= 1; + break; default: error("unexpected %d", node->type); } @@ -522,7 +593,10 @@ static void codegen(Node *node) { while (node != NULL) { - gen_function(node); + if (node->type == NOD_GLOBAL) + gen_globaldec(node); + else + gen_function(node); node = node->next; } } @@ -533,8 +607,14 @@ parse(Token *tok) { Node head = {0}; Node *cur = &head; - while (tok->type != TOK_EOF) + while (tok->type != TOK_EOF) { + if (equal(tok, "global")) { + cur = cur->next = global(&tok, tok); + continue; + } + cur = cur->next = function(&tok, tok); + } return head.next; } @@ -1,18 +1,23 @@ #!/bin/sh function test() { - CODE="$1" + QUIET="$1" + CODE="$2" echo "--- $CODE ---" ./build/golem "$CODE" >"build/tmp.orgaasm" - cat "build/tmp.orgaasm" + [ "$QUIET" != "-q" ] && cat "build/tmp.orgaasm" orgaasm "build/tmp.orgaasm" "build/tmp.rom" orgaemu "build/tmp.rom" - echo "" + [ "$QUIET" != "-q" ] && echo "" } tup || exit 1 -test "main(){5 + 2; return 4;}" -test "main(){6 + 3;}" -test "main(){'a' - 'b';}" -test "main(){ fizz(50 + buzz() - 3) * 4; } fizz() { return 3; } buzz() { return 42; }" +test "$1" "main(){5 + 2; return 4;}" +test "$1" "main(){6 + 3;}" +test "$1" "main(){'a' - 'b';}" +test "$1" "main(){ fizz(50 + buzz() - 3) * 4; } fizz() { return 3; } buzz() { return 42; }" +test "$1" "global abc; main(){ return abc; }" +test "$1" "global abc = 5; main(){ return abc; }" +test "$1" "main(){ return abc; } global abc = 5;" +test "$1" "global abc = 5; main(){ inc(); return abc; } inc() { abc = abc + 1; }" rm -f build/tmp.* |