aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-18 22:19:24 +0200
committerBad Diode <bd@badd10de.dev>2024-06-18 22:19:24 +0200
commitfaf69726d4fc619bc55a2c1105bd542673cce342 (patch)
tree8145281c300f9248c834deabf003811589e3eec8
parentad14773fcebdbd989c1d7c3245b59a1cae666d2f (diff)
downloadbdl-faf69726d4fc619bc55a2c1105bd542673cce342.tar.gz
bdl-faf69726d4fc619bc55a2c1105bd542673cce342.zip
Add basic while loop
-rw-r--r--Makefile7
-rw-r--r--src/main.c21
-rw-r--r--tests/loops.bad18
3 files changed, 43 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 5af466c..732766e 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ BUILD_DIR := build
7TESTS_DIR := tests 7TESTS_DIR := tests
8TEST_FILES := $(wildcard $(TESTS_DIR)/*.bad) 8TEST_FILES := $(wildcard $(TESTS_DIR)/*.bad)
9SRC_MAIN := $(SRC_DIR)/main.c 9SRC_MAIN := $(SRC_DIR)/main.c
10SRC_RUN := tests/conditionals.bad 10SRC_RUN := tests/loops.bad
11WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h") 11WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h")
12INC_DIRS := $(shell find $(SRC_DIR) -type d) 12INC_DIRS := $(shell find $(SRC_DIR) -type d)
13INC_FLAGS := $(addprefix -I,$(INC_DIRS)) 13INC_FLAGS := $(addprefix -I,$(INC_DIRS))
@@ -74,8 +74,11 @@ graph-symbols: $(BIN)
74 74
75tests: $(BIN) 75tests: $(BIN)
76 @for name in $(TEST_FILES); do\ 76 @for name in $(TEST_FILES); do\
77 line=" OK";\
77 printf "$${name}\r" ;\ 78 printf "$${name}\r" ;\
78 $(BIN) $${name} && printf "$${name}\tOK!\n";\ 79 $(BIN) $${name} \
80 && printf "$$line\r" \
81 && printf "$${name}\n";\
79 done 82 done
80 83
81# Remove build directory. 84# Remove build directory.
diff --git a/src/main.c b/src/main.c
index 1c0d2e1..666a664 100644
--- a/src/main.c
+++ b/src/main.c
@@ -82,6 +82,7 @@ typedef enum NodeKind {
82 NODE_ENUM, 82 NODE_ENUM,
83 NODE_BREAK, 83 NODE_BREAK,
84 NODE_CONTINUE, 84 NODE_CONTINUE,
85 NODE_WHILE,
85 // Helpers. 86 // Helpers.
86 NODE_SYMBOL_IDX, 87 NODE_SYMBOL_IDX,
87 NODE_TYPE, 88 NODE_TYPE,
@@ -135,6 +136,7 @@ Str node_str[] = {
135 [NODE_ENUM] = cstr("ENUM"), 136 [NODE_ENUM] = cstr("ENUM"),
136 [NODE_BREAK] = cstr("BREAK"), 137 [NODE_BREAK] = cstr("BREAK"),
137 [NODE_CONTINUE] = cstr("CONTINUE"), 138 [NODE_CONTINUE] = cstr("CONTINUE"),
139 [NODE_WHILE] = cstr("WHILE"),
138 // Helpers. 140 // Helpers.
139 [NODE_TYPE] = cstr("TYPE"), 141 [NODE_TYPE] = cstr("TYPE"),
140 [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), 142 [NODE_ARR_TYPE] = cstr("TYPE (ARR)"),
@@ -172,6 +174,10 @@ typedef struct Node {
172 struct Node *var_val; 174 struct Node *var_val;
173 }; 175 };
174 struct { 176 struct {
177 struct Node *while_cond;
178 struct Node *while_expr;
179 };
180 struct {
175 struct Node *cond_if; 181 struct Node *cond_if;
176 struct Node *cond_expr; 182 struct Node *cond_expr;
177 struct Node *cond_else; 183 struct Node *cond_else;
@@ -209,6 +215,7 @@ typedef struct Parser {
209 // Error handling. 215 // Error handling.
210 bool err; 216 bool err;
211 bool panic; 217 bool panic;
218 Str file_name;
212 219
213 // Storage. 220 // Storage.
214 Node **nodes; 221 Node **nodes;
@@ -328,7 +335,8 @@ parse_emit_err(Parser *parser, Token token, Str msg) {
328 if (parser->panic) return; 335 if (parser->panic) return;
329 parser->panic = true; 336 parser->panic = true;
330 parser->err = true; 337 parser->err = true;
331 eprint("%d:%d: error: %s", token.line, token.col, msg); 338 eprint("%s:%d:%d: error: %s", parser->file_name, token.line, token.col,
339 msg);
332 340
333 if (token.kind == TOK_EOF) { 341 if (token.kind == TOK_EOF) {
334 eprintln(" at end of the file"); 342 eprintln(" at end of the file");
@@ -675,6 +683,16 @@ parse_keyword(Parser *parser) {
675 node = node_alloc(parser, NODE_CONTINUE, prev); 683 node = node_alloc(parser, NODE_CONTINUE, prev);
676 if (!node) return; 684 if (!node) return;
677 } break; 685 } break;
686 case TOK_WHILE: {
687 node = node_alloc(parser, NODE_WHILE, prev);
688 if (!node) return;
689 parse_expr(parser, PREC_LOW);
690 node->while_cond = array_pop(parser->nodes);
691 parse_consume(parser, TOK_ASSIGN,
692 cstr("malformed while expression"));
693 parse_expr(parser, PREC_LOW);
694 node->while_expr = array_pop(parser->nodes);
695 } break;
678 default: return; // Unreachable. 696 default: return; // Unreachable.
679 } 697 }
680 array_push(parser->nodes, node, parser->storage); 698 array_push(parser->nodes, node, parser->storage);
@@ -1009,6 +1027,7 @@ process_file(Str path) {
1009 Parser parser = { 1027 Parser parser = {
1010 .tokens = tokens, 1028 .tokens = tokens,
1011 .storage = &lexer_arena, 1029 .storage = &lexer_arena,
1030 .file_name = path,
1012 }; 1031 };
1013 array_init(parser.nodes, 256, parser.storage); 1032 array_init(parser.nodes, 256, parser.storage);
1014 parse_advance(&parser); 1033 parse_advance(&parser);
diff --git a/tests/loops.bad b/tests/loops.bad
new file mode 100644
index 0000000..5221844
--- /dev/null
+++ b/tests/loops.bad
@@ -0,0 +1,18 @@
1; The most basic loop is the while loop.
2while abc = "heelo"
3
4while 1 + 2 == 3 = {
5 "hello"
6}
7
8while symbol = {
9 "hello"
10}
11
12
13; We could use some sugar for this.
14let i = 0
15while i < 10 = {
16 "hello"
17 set i = i + 1
18}