summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-10 01:30:17 +0200
committerkdx <kikoodx@paranoici.org>2023-06-10 01:30:17 +0200
commitdb48a58769ac267a8de49f456cb4e5b27bfddb40 (patch)
treeb42796d9b04049296d451c458adb4105facaf17e
parent0e5b99fbbb46d5e91feca6f6f862f11359b92aa7 (diff)
downloadgolem-db48a58769ac267a8de49f456cb4e5b27bfddb40.tar.gz
global assign
-rw-r--r--src/main.c92
-rwxr-xr-xtesting.sh19
2 files changed, 98 insertions, 13 deletions
diff --git a/src/main.c b/src/main.c
index 0d810af..f082416 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}
diff --git a/testing.sh b/testing.sh
index d579990..e846bde 100755
--- a/testing.sh
+++ b/testing.sh
@@ -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.*