summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-16 07:04:54 +0200
committerkdx <kikoodx@paranoici.org>2023-06-16 07:14:40 +0200
commit6458a1a6c483f82c2499e867b553ec92efee26c4 (patch)
treea27e74e6bbb04b05f77251b5c85fe062a0d7929b
parent0752019a86028f3e9ca93591a2586fce3b139fde (diff)
downloadgolem-6458a1a6c483f82c2499e867b553ec92efee26c4.tar.gz
uwu error printing
-rw-r--r--.gitignore2
-rw-r--r--Tupfile2
-rw-r--r--samples/move.golem20
-rw-r--r--src/main.c235
4 files changed, 166 insertions, 93 deletions
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 <stdlib.h>
#include <string.h>
+#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);