diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 11:35:28 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 11:35:28 +0200 |
| commit | dd52ccd9319aa847cddc486519075b806c9e9092 (patch) | |
| tree | df290f8972aa6eb164fad7258002ccb95cf648bf | |
| parent | 768bbdd137f5b205e4282bd79572681aef4514e3 (diff) | |
feat: emmit a decltype of a difference
| -rw-r--r-- | Makefile | 13 | ||||
| -rw-r--r-- | eval.c | 73 | ||||
| -rw-r--r-- | eval.h | 23 | ||||
| -rw-r--r-- | main.c | 7 |
4 files changed, 108 insertions, 8 deletions
@@ -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 @@ -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; +} @@ -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); @@ -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; } |
