diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 63 |
1 files changed, 55 insertions, 8 deletions
@@ -337,7 +337,7 @@ new_num(int val) static Node *stmt(Token **rest, Token *tok); static Node *function(Token **rest, Token *tok); -void define(Token **rest, Token *tok); +static void define(Token **rest, Token *tok); static Node *global(Token **rest, Token *tok); static Node *local(Token **rest, Token *tok); static Node *expr(Token **rest, Token *tok); @@ -392,14 +392,14 @@ function(Token **rest, Token *tok) return node; } -void +static void define(Token **rest, Token *tok) { tok = skip(tok, "define"); Node *store = new_word(tok); tok = skip(tok->next, "="); - store->val = get_number(tok); - *rest = skip(tok->next, ";"); + store->rhs = expr(&tok, tok); + *rest = skip(tok, ";"); store->type = NOD_DEFINE; store->next = defines; @@ -417,8 +417,8 @@ global(Token **rest, Token *tok) if (equal(tok, "[")) { tok = tok->next; - node->lhs = new_num(get_number(tok)); - tok = skip(tok->next, "]"); + node->lhs = expr(&tok, tok); + tok = skip(tok, "]"); } if (equal(tok, "=")) { @@ -918,6 +918,8 @@ gen_expr(Node *node) printf("\t%s\n", op); } +static int const_expr(Node *node); + static void gen_globaldec(Node *node) { @@ -925,7 +927,8 @@ gen_globaldec(Node *node) if (node->lhs != NULL) { printf("\t,__gla_%.*s\n", node->len, node->loc); printf("@__gla_%.*s\n", node->len, node->loc); - for (int i = 0; i < node->lhs->val; i++) + const int len = const_expr(node->lhs); + for (int i = 0; i < len; i++) printf("\t%04x\n", node->val); } else printf("\t%04x\n", node->val); @@ -950,6 +953,49 @@ gen_fncall(Node *node) } } +static int +get_define(Node *node) +{ + const int define_idx = node_find(defines, node); + if (define_idx != -1) + return const_expr(node_get(defines, define_idx)->rhs); + error("define '%.*s doesn't exist\n", node->len, node->loc); + return 0; +} + +static int +const_expr(Node *node) +{ + Node *const lhs = node->lhs; + Node *const rhs = node->rhs; + + switch (node->type) { + case NOD_ADD: return const_expr(lhs) + const_expr(rhs); + case NOD_SUB: return const_expr(lhs) - const_expr(rhs); + case NOD_MUL: return const_expr(lhs) * const_expr(rhs); + case NOD_DIV: return const_expr(lhs) / const_expr(rhs); + case NOD_EQU: return const_expr(lhs) == const_expr(rhs); + case NOD_NEQ: return const_expr(lhs) != const_expr(rhs); + case NOD_LT: return const_expr(lhs) < const_expr(rhs); + case NOD_LTE: return const_expr(lhs) <= const_expr(rhs); + case NOD_GT: return const_expr(lhs) > const_expr(rhs); + case NOD_GTE: return const_expr(lhs) >= const_expr(rhs); + case NOD_AND: return const_expr(lhs) & const_expr(rhs); + case NOD_OR: return const_expr(lhs) | const_expr(rhs); + case NOD_XOR: return const_expr(lhs) ^ const_expr(rhs); + default: break; + } + + switch (node->type) { + case NOD_NUM: return node->val; + case NOD_WORD: return get_define(node); + default: break; + } + + error("const expr doesn't support %d expression", node->type); + return 0; +} + static void gen_variableget(Node *node) { @@ -957,7 +1003,8 @@ gen_variableget(Node *node) const int found = node_find(locals, node); if (define_idx != -1) - printf("\tLIT %04x\n", node_get(defines, define_idx)->val); + printf("\tLIT %04x\n", + (unsigned)const_expr(node_get(defines, define_idx)->rhs) % 0x10000); else if (found != -1) { printf("\tLIT ,__stack_ptr LDA\n"); if (locals_size - found - 1) |