From 6458a1a6c483f82c2499e867b553ec92efee26c4 Mon Sep 17 00:00:00 2001 From: kdx Date: Fri, 16 Jun 2023 07:04:54 +0200 Subject: uwu error printing --- .gitignore | 2 + Tupfile | 2 - samples/move.golem | 20 ++--- src/main.c | 235 ++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 166 insertions(+), 93 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c03b489 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.tup +/build diff --git a/Tupfile b/Tupfile index 00c26fe..e615e01 100644 --- a/Tupfile +++ b/Tupfile @@ -6,5 +6,3 @@ NAME = golemc : foreach src/*.c |> $(CC) $(CFLAGS) -c -o %o %f |> build/%B.o : build/*.o |> $(LD) -o %o %f $(LIBS) |> build/$(NAME) - -.gitignore diff --git a/samples/move.golem b/samples/move.golem index f29a899..feece58 100644 --- a/samples/move.golem +++ b/samples/move.golem @@ -11,19 +11,13 @@ main() { } -update() { - input_update() |> player_update(); -} +update() => input_update() |> player_update(); -erase() { - player_erase(); -} +erase() => player_erase(); -draw() { - player_draw(); -} +draw() => player_draw(); global input_left; @@ -50,14 +44,10 @@ player_update() { } -player_erase() { - pset(player_x, player_y, 0x1111); -} +player_erase() => pset(player_x, player_y, 0x1111); -player_draw() { - pset(player_x, player_y, 0xffff); -} +player_draw() => pset(player_x, player_y, 0xffff); pset(x, y, c) { diff --git a/src/main.c b/src/main.c index 0eb841c..4aa53da 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,45 @@ #include #include +#define ANSI_RED "\x1b[31m" +#define ANSI_GREEN "\x1b[32m" +#define ANSI_YELLOW "\x1b[33m" +#define ANSI_BLUE "\x1b[34m" +#define ANSI_MAGENTA "\x1b[35m" +#define ANSI_CYAN "\x1b[36m" +#define ANSI_RESET "\x1b[0m" + +static char *source = NULL; + +static int +get_line_number(const char *p) +{ + if (p == NULL) + return 0; + + int line = 1; + + for (char *s = source; *s != '\0'; s++) { + if (s == p) + return line; + line += (*s == '\n'); + } + return line; +} + +static char * +get_error_line(int target) +{ + int line = 1; + char *s = source; + + while (line < target) { + line += (*s == '\n'); + s += 1; + } + return s; +} + typedef enum { TOK_PUNCT, TOK_NUM, @@ -29,27 +68,62 @@ struct Token { int val; char *loc; int len; + int line_no; }; +static char *phase = "preparation"; + +static void +verror(const char *fmt, va_list va) +{ + fprintf(stderr, "%s: " ANSI_RED "error: " ANSI_RESET, phase); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); +} + static void -_error(const char *fmt, ...) { - fprintf(stderr, "error:"); +error(const char *fmt, ...) { va_list va; va_start(va, fmt); - vfprintf(stderr, fmt, va); + verror(fmt, va); va_end(va); - fprintf(stderr, "\n"); exit(1); } -#define error(fmt, ...) _error("%d: " fmt, __LINE__, __VA_ARGS__); +static void +error_loc(const char *loc, const char *fmt, ...) { + va_list va; + va_start(va, fmt); + verror(fmt, va); + va_end(va); + + const int line_no = get_line_number(loc); + if (line_no == 0) + exit(1); + + const char *line = get_error_line(line_no); + const char *line_end = strchr(line, '\n'); + if (line_end == NULL) + fprintf(stderr, "%5d | %s\n", line_no, line); + else + fprintf(stderr, "%5d | %.*s\n", line_no, (int)(line_end - line), line); + + int spaces = 8; + for (int i = 0; i < loc - line; i++) + spaces += 1 + 7 * (line[i] == '\t'); + + fprintf(stderr, "%*s", spaces, ""); + fprintf(stderr, ANSI_RED "^" ANSI_RESET "\n"); + + exit(1); +} static void expect(const Token *tok, TokenType type) { if (tok->type != type) - error("expected a %s, got %s '%.*s'", - str_tok[type], str_tok[tok->type], tok->len, tok->loc); + error_loc(tok->loc, "expected a %s, got %s '%.*s'", + str_tok[type], str_tok[tok->type], tok->len, tok->loc); } static bool @@ -62,7 +136,8 @@ static Token * skip(Token *tok, char *s) { if (!equal(tok, s)) - error("expected '%s'; got '%.*s'", s, tok->len, tok->loc); + error_loc(tok->loc, "expected '%s'; got '%.*s'", s, tok->len, + tok->loc); return tok->next; } @@ -157,7 +232,7 @@ tokenize(char *p) if (*p == '"') { char *end = strchr(p + 1, '"'); if (end == NULL) - error("unclosed double quotes", 0); + error_loc(p, "unclosed double quotes"); cur = cur->next = new_token(TOK_STRING, p, end + 1); p = end + 1; continue; @@ -167,7 +242,7 @@ tokenize(char *p) char *q = p; const int c = escaped_char(p + 1, &p); if (*p != '\'') - error("unclosed single quotes", 0); + error_loc(p, "unclosed single quotes"); p += 1; cur = cur->next = new_token(TOK_NUM, q, p); cur->val = (unsigned char)c; @@ -189,7 +264,7 @@ tokenize(char *p) continue; } - error("invalid token '%c'", *p); + error_loc(p, "invalid token '%c'", *p); } cur->next = new_token(TOK_EOF, p, p); @@ -294,43 +369,45 @@ node_get(Node *node, int idx) } static Node * -new_node(NodeType type) +new_node(NodeType type, Token *tok) { Node *const node = calloc(1, sizeof(Node)); if (node == NULL) error("calloc failed", 0); node->type = type; + if (tok != NULL) { + node->loc = tok->loc; + node->len = tok->len; + } return node; } static Node * new_word(Token *tok) { - Node *const node = new_node(NOD_WORD); - node->loc = tok->loc; - node->len = tok->len; + Node *const node = new_node(NOD_WORD, tok); return node; } static Node * -new_binary(NodeType type, Node *lhs, Node *rhs) +new_binary(NodeType type, Token *tok, Node *lhs, Node *rhs) { - Node *const node = new_node(type); + Node *const node = new_node(type, tok); node->lhs = lhs; node->rhs = rhs; return node; } static Node * -new_unary(NodeType type, Node *node) +new_unary(NodeType type, Token *tok, Node *node) { - return new_binary(type, node, NULL); + return new_binary(type, tok, node, NULL); } static Node * -new_num(int val) +new_num(int val, Token *tok) { - Node *const node = new_node(NOD_NUM); + Node *const node = new_node(NOD_NUM, tok); node->val = val; return node; } @@ -370,7 +447,7 @@ static int strings_size; static Node * function(Token **rest, Token *tok) { - Node *const node = new_node(NOD_FUN); + Node *const node = new_node(NOD_FUN, tok); node->lhs = new_word(tok); tok = skip(tok->next, "("); @@ -435,7 +512,7 @@ static Node * local(Token **rest, Token *tok) { tok = skip(tok, "local"); - Node *const node = new_unary(NOD_LOCAL, new_word(tok)); + Node *const node = new_unary(NOD_LOCAL, tok, new_word(tok)); *rest = skip(tok->next, ";"); return node; } @@ -453,17 +530,17 @@ static Node for (;;) { if (equal(tok, "&")) { - node = new_binary(NOD_AND, node, equality(&tok, tok->next)); + node = new_binary(NOD_AND, tok, node, equality(&tok, tok->next)); continue; } if (equal(tok, "^")) { - node = new_binary(NOD_XOR, node, equality(&tok, tok->next)); + node = new_binary(NOD_XOR, tok, node, equality(&tok, tok->next)); continue; } if (equal(tok, "|")) { - node = new_binary(NOD_OR, node, equality(&tok, tok->next)); + node = new_binary(NOD_OR, tok, node, equality(&tok, tok->next)); continue; } @@ -480,12 +557,12 @@ static Node for (;;) { if (equal(tok, "==")) { - node = new_binary(NOD_EQU, node, relational(&tok, tok->next)); + node = new_binary(NOD_EQU, tok, node, relational(&tok, tok->next)); continue; } if (equal(tok, "!=")) { - node = new_binary(NOD_NEQ, node, relational(&tok, tok->next)); + node = new_binary(NOD_NEQ, tok, node, relational(&tok, tok->next)); continue; } @@ -501,22 +578,22 @@ static Node for (;;) { if (equal(tok, "<")) { - node = new_binary(NOD_LT, node, add(&tok, tok->next)); + node = new_binary(NOD_LT, tok, node, add(&tok, tok->next)); continue; } if (equal(tok, "<=")) { - node = new_binary(NOD_LTE, node, add(&tok, tok->next)); + node = new_binary(NOD_LTE, tok, node, add(&tok, tok->next)); continue; } if (equal(tok, ">")) { - node = new_binary(NOD_GT, node, add(&tok, tok->next)); + node = new_binary(NOD_GT, tok, node, add(&tok, tok->next)); continue; } if (equal(tok, ">=")) { - node = new_binary(NOD_GTE, node, add(&tok, tok->next)); + node = new_binary(NOD_GTE, tok, node, add(&tok, tok->next)); continue; } @@ -533,12 +610,12 @@ add(Token **rest, Token *tok) for (;;) { if (equal(tok, "+")) { - node = new_binary(NOD_ADD, node, mul(&tok, tok->next)); + node = new_binary(NOD_ADD, tok, node, mul(&tok, tok->next)); continue; } if (equal(tok, "-")) { - node = new_binary(NOD_SUB, node, mul(&tok, tok->next)); + node = new_binary(NOD_SUB, tok, node, mul(&tok, tok->next)); continue; } @@ -555,12 +632,12 @@ mul(Token **rest, Token *tok) for (;;) { if (equal(tok, "*")) { - node = new_binary(NOD_MUL, node, primary(&tok, tok->next)); + node = new_binary(NOD_MUL, tok, node, primary(&tok, tok->next)); continue; } if (equal(tok, "/")) { - node = new_binary(NOD_DIV, node, primary(&tok, tok->next)); + node = new_binary(NOD_DIV, tok, node, primary(&tok, tok->next)); continue; } @@ -602,16 +679,16 @@ primary(Token **rest, Token *tok) } if (equal(tok, "[")) { + Node *node = new_node(NOD_DEREF, tok); tok = tok->next; - Node *node = new_node(NOD_DEREF); node->lhs = expr(&tok, tok); *rest = skip(tok, "]"); return node; } if (equal(tok, "&")) { + Node *node = new_node(NOD_REF, tok); tok = tok->next; - Node *node = new_node(NOD_REF); expect(tok, TOK_WORD); node->lhs = new_word(tok); *rest = tok->next; @@ -619,15 +696,13 @@ primary(Token **rest, Token *tok) } if (tok->type == TOK_NUM) { - Node *node = new_num(tok->val); + Node *node = new_num(tok->val, tok); *rest = tok->next; return node; } if (tok->type == TOK_STRING) { - Node *node = new_node(NOD_STRING); - node->loc = tok->loc; - node->len = tok->len; + Node *node = new_node(NOD_STRING, tok); *rest = tok->next; return node; } @@ -651,10 +726,7 @@ primary(Token **rest, Token *tok) return node; } - fprintf(stderr, "'%.*s'\n", tok->len, tok->loc); - if (tok->next != NULL) - fprintf(stderr, "'%.*s'\n", tok->next->len, tok->next->loc); - error("expected an expression", 0); + error_loc(tok->loc, "expected an expression"); return NULL; } @@ -705,19 +777,20 @@ static Node * empty_stmt(Token **rest, Token *tok) { *rest = skip(tok, ";"); - return new_node(NOD_EMPTY_STMT); + return new_node(NOD_EMPTY_STMT, tok); } static Node * block_stmt(Token **rest, Token *tok) { - tok = skip(tok, "{"); - if (equal(tok, "}")) { - *rest = tok->next; - return new_node(NOD_EMPTY_STMT); + skip(tok, "{"); + if (equal(tok->next, "}")) { + *rest = tok->next->next; + return new_node(NOD_EMPTY_STMT, tok); } - Node *const node = new_node(NOD_BLOCK_STMT); + Node *const node = new_node(NOD_BLOCK_STMT, tok); + tok = tok->next; Node head = {0}; Node *cur = &head; @@ -734,7 +807,7 @@ block_stmt(Token **rest, Token *tok) static Node * expr_stmt(Token **rest, Token *tok) { - Node *const node = new_unary(NOD_EXPR_STMT, expr(&tok, tok)); + Node *const node = new_unary(NOD_EXPR_STMT, tok, expr(&tok, tok)); *rest = skip(tok, ";"); return node; } @@ -748,9 +821,9 @@ return_stmt(Token **rest, Token *tok) tok = skip(tok, "return"); Node *node; if (equal(tok, ";")) - node = new_unary(NOD_RETURN_STMT, new_num(0)); + node = new_unary(NOD_RETURN_STMT, tok, new_num(0, NULL)); else - node = new_unary(NOD_RETURN_STMT, expr(&tok, tok)); + node = new_unary(NOD_RETURN_STMT, tok, expr(&tok, tok)); *rest = skip(tok, ";"); return node; } @@ -758,23 +831,23 @@ return_stmt(Token **rest, Token *tok) static Node * break_stmt(Token **rest, Token *tok) { - tok = skip(tok, "break"); - *rest = skip(tok, ";"); - return new_node(NOD_BREAK_STMT); + *rest = skip(skip(tok, "break"), ";"); + return new_node(NOD_BREAK_STMT, tok); } static Node * slp_stmt(Token **rest, Token *tok) { *rest = skip(skip(tok, "slp"), ";"); - return new_node(NOD_SLP_STMT); + return new_node(NOD_SLP_STMT, tok); } static Node * dbg_stmt(Token **rest, Token *tok) { + Token *const og = tok; tok = skip(tok, "dbg"); - Node *const node = new_unary(NOD_DBG_STMT, expr(&tok, tok)); + Node *const node = new_unary(NOD_DBG_STMT, og, expr(&tok, tok)); *rest = skip(tok, ";"); return node; } @@ -782,8 +855,9 @@ dbg_stmt(Token **rest, Token *tok) static Node * wrt_stmt(Token **rest, Token *tok) { + Token *const og = tok; tok = skip(tok, "wrt"); - Node *const node = new_unary(NOD_WRT_STMT, expr(&tok, tok)); + Node *const node = new_unary(NOD_WRT_STMT, og, expr(&tok, tok)); *rest = skip(tok, ";"); return node; } @@ -791,8 +865,9 @@ wrt_stmt(Token **rest, Token *tok) static Node * red_stmt(Token **rest, Token *tok) { + Token *const og = tok; tok = skip(tok, "red"); - Node *const node = new_unary(NOD_RED_STMT, expr(&tok, tok)); + Node *const node = new_unary(NOD_RED_STMT, og, expr(&tok, tok)); *rest = skip(tok, ";"); return node; } @@ -800,12 +875,13 @@ red_stmt(Token **rest, Token *tok) static Node * postfix_stmt(Token **rest, Token *tok) { + Token *const og = tok; Node *lhs; expect(tok, TOK_WORD); lhs = new_word(tok); tok = tok->next; expect(tok, TOK_PUNCT); - Node *const node = new_binary(NOD_POSTFIX_STMT, lhs, new_word(tok)); + Node *const node = new_binary(NOD_POSTFIX_STMT, og, lhs, new_word(tok)); *rest = skip(tok->next, ";"); return node; } @@ -815,8 +891,8 @@ assign_stmt(Token **rest, Token *tok) { Node *lhs; if (equal(tok, "[")) { + lhs = new_node(NOD_DEREF, tok); tok = tok->next; - lhs = new_node(NOD_DEREF); lhs->lhs = expr(&tok, tok); *rest = skip(tok, "]"); } else { @@ -824,7 +900,7 @@ assign_stmt(Token **rest, Token *tok) lhs = new_word(tok); } skip(tok->next, "="); - Node *const node = new_binary(NOD_ASSIGN_STMT, lhs, expr(&tok, tok->next->next)); + Node *const node = new_binary(NOD_ASSIGN_STMT, tok, lhs, expr(&tok, tok->next->next)); *rest = skip(tok, ";"); return node; } @@ -832,8 +908,8 @@ assign_stmt(Token **rest, Token *tok) static Node * ifelse_stmt(Token **rest, Token *tok) { + Node *const node = new_node(NOD_IFELSE_STMT, tok); tok = skip(tok, "if"); - Node *const node = new_node(NOD_IFELSE_STMT); node->lhs = expr(&tok, tok); node->rhs = stmt(&tok, tok); @@ -849,8 +925,9 @@ ifelse_stmt(Token **rest, Token *tok) static Node * loop_stmt(Token **rest, Token *tok) { + Token *const og = tok; tok = skip(tok, "loop"); - Node *const node = new_unary(NOD_LOOP_STMT, stmt(&tok, tok)); + Node *const node = new_unary(NOD_LOOP_STMT, og, stmt(&tok, tok)); *rest = tok; return node; } @@ -917,7 +994,7 @@ gen_expr(Node *node) } if (op == NULL) - error("invalid expression %d", node->type); + error_loc(node->loc, "invalid expression %d", node->type); printf("\t%s\n", op); } @@ -962,7 +1039,8 @@ 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); + error_loc(node->loc, "define '%.*s' doesn't exist", node->len, + node->loc); return 0; } @@ -995,7 +1073,8 @@ const_expr(Node *node) default: break; } - error("const expr doesn't support %d expression", node->type); + error_loc(node->loc, "const expr doesn't support %d expression", + node->type); return 0; } @@ -1030,7 +1109,7 @@ gen_deref(Node *node) static void gen_string(Node *node) { - Node *store = new_node(0); + Node *store = new_node(0, NULL); store->lhs = node; store->next = strings; strings = store; @@ -1138,7 +1217,7 @@ gen_stmt(Node *node, Node *fname, int break_lbl) break; case NOD_BREAK_STMT: if (break_lbl == -1) - error("break statement outside of loop", 0); + error_loc(node->loc, "break statement outside of loop"); printf("\tJMP ,__lbl_%x\n", break_lbl); break; case NOD_SLP_STMT: @@ -1191,7 +1270,7 @@ gen_stmt(Node *node, Node *fname, int break_lbl) printf("@__lbl_%x\n", lbl + 1); break; default: - error("unexpected %d", node->type); + error_loc(node->loc, "unexpected %d", node->type); } } @@ -1271,7 +1350,7 @@ codegen(Node *node) char *q = strings->lhs->loc + k; const int c = escaped_char(q, &q); if (c == '"') /* TODO: handle this */ - error("can't escape double quotes", 0); + error_loc(q, "can't escape double quotes", 0); printf("\t%04x\n", (unsigned)c); k = q - strings->lhs->loc; } @@ -1331,12 +1410,16 @@ main(int argc, char **argv) FILE *const fp = fopen(argv[1], "rb"); if (fp == NULL) - error("fopen failed", 0); - Token *const tok = tokenize(drain(fp)); + error("%m: '%s'", argv[1]); + source = drain(fp); fclose(fp); + phase = "lex"; + Token *const tok = tokenize(source); + phase = "parse"; Node *node = parse(tok); + phase = "codegen"; codegen(node); assert(depth == 0); -- cgit v1.2.3