hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 11:35:28 +0200
committerhachem <im@hachem.wtf>2026-09-19 11:35:28 +0200
commitdd52ccd9319aa847cddc486519075b806c9e9092 (patch)
treedf290f8972aa6eb164fad7258002ccb95cf648bf
parent768bbdd137f5b205e4282bd79572681aef4514e3 (diff)
feat: emmit a decltype of a difference
-rw-r--r--Makefile13
-rw-r--r--eval.c73
-rw-r--r--eval.h23
-rw-r--r--main.c7
4 files changed, 108 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index c107cb3..48363ba 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
-CC = cc
+CC = clang
LEX = flex
YACC = bison
CFLAGS = -std=c17 -Wall -Wextra -Werror -Wpedantic -O2 -Ibin
-SOURCES = ast.c ast.h lexer.h main.c
-OBJECTS = bin/lexer.o bin/parser.o bin/ast.o bin/main.o
+SOURCES = ast.c ast.h eval.c eval.h lexer.h main.c
+OBJECTS = bin/lexer.o bin/parser.o bin/ast.o bin/eval.o bin/main.o
SANITIZE = -g -O0 -fsanitize=address,undefined
.PHONY: all debug check format lint clean
@@ -31,8 +31,9 @@ bin/parser.o: bin/parser.c
bin/%.o: %.c | bin
$(CC) $(CFLAGS) -c -o $@ $<
-bin/main.o: ast.h lexer.h
-bin/ast.o: ast.h lexer.h
+bin/main.o: ast.h eval.h lexer.h
+bin/ast.o: ast.h lexer.h
+bin/eval.o: eval.h ast.h
debug: CFLAGS += $(SANITIZE)
debug: clean sfinae
@@ -47,7 +48,7 @@ format:
clang-format -i $(SOURCES)
lint:
- clang-tidy ast.c main.c -- -std=c17 -Ibin
+ clang-tidy ast.c eval.c main.c -- -std=c17 -Ibin
clean:
rm -rf bin sfinae
diff --git a/eval.c b/eval.c
new file mode 100644
index 0000000..5841566
--- /dev/null
+++ b/eval.c
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <stdio.h>
+
+#include "eval.h"
+
+static int evaluate_value(const struct Node* node, long* out)
+{
+ switch (node->kind)
+ {
+ case VALUE_DIFFERENCE:
+ *out = (long)node->first->character - (long)node->second->character;
+ return 0;
+ default: break;
+ }
+
+ assert(!"the parser handed a non-value where a value goes");
+ return 1;
+}
+
+static int evaluate_type(const struct Node* node, struct Type* out)
+{
+ out->kind = KIND_VOID;
+ out->number = 0;
+ switch (node->kind)
+ {
+ case TYPE_DECLTYPE:
+ if (evaluate_value(node->first, &out->number))
+ return 1;
+ out->kind = KIND_VALUE;
+ return 0;
+ default: break;
+ }
+
+ assert(!"the parser handed a non-type where a type goes");
+ return 1;
+}
+
+static enum RunStatus emit(const struct Node* node)
+{
+ struct Type type;
+ if (evaluate_type(node->first, &type))
+ return RUN_FAILED;
+
+ if (type.kind == KIND_VALUE)
+ (void)printf("%ld\n", type.number);
+ return RUN_DONE;
+}
+
+static enum RunStatus execute_one(const struct Node* node)
+{
+ switch (node->kind)
+ {
+ case STMT_EMIT: return emit(node);
+ default: break;
+ }
+
+ assert(!"the parser handed a non-statement where a statement goes");
+ return RUN_FAILED;
+}
+
+enum RunStatus execute(const struct Node* statement)
+{
+ while (statement != NULL)
+ {
+ enum RunStatus status = execute_one(statement);
+ if (status != RUN_DONE)
+ return status;
+
+ statement = statement->next;
+ }
+
+ return RUN_DONE;
+}
diff --git a/eval.h b/eval.h
new file mode 100644
index 0000000..8b4a5f6
--- /dev/null
+++ b/eval.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "ast.h"
+
+enum TypeKind
+{
+ KIND_VOID,
+ KIND_VALUE
+};
+
+struct Type
+{
+ enum TypeKind kind;
+ long number;
+};
+
+enum RunStatus
+{
+ RUN_DONE,
+ RUN_FAILED
+};
+
+enum RunStatus execute(const struct Node* statement);
diff --git a/main.c b/main.c
index 2d358d8..682b9db 100644
--- a/main.c
+++ b/main.c
@@ -1,16 +1,19 @@
#include <stdio.h>
#include "ast.h"
+#include "eval.h"
#include "lexer.h"
extern struct Node* program_root;
int yyparse(void);
-static int parse_program(void)
+static int run_program(void)
{
int status = yyparse();
if (status != 0 || lexer_failed())
status = 1;
+ else
+ status = execute(program_root) == RUN_FAILED;
node_free(program_root);
program_root = NULL;
@@ -32,7 +35,7 @@ int main(int argc, char** argv)
return 1;
}
- int status = parse_program();
+ int status = run_program();
(void)fclose(yyin);
return status;
}