From dd52ccd9319aa847cddc486519075b806c9e9092 Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 19 Sep 2026 11:35:28 +0200 Subject: feat: emmit a decltype of a difference --- Makefile | 13 ++++++------ eval.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ eval.h | 23 ++++++++++++++++++++ main.c | 7 +++++-- 4 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 eval.c create mode 100644 eval.h 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 +#include + +#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 #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; } -- cgit v1.3