commit 2a9968c4cec994ddfd8e3fef302800deb70ad06b Author: Dominic Grimm Date: Thu Dec 22 13:19:33 2022 +0100 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..bc48ab4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(hydroforth) + +file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) +add_executable(hydroforth ${SOURCES}) + +target_include_directories(hydroforth PRIVATE ${PROJECT_SOURCE_DIR}/include) diff --git a/include/hydroforth/hydroforth.h b/include/hydroforth/hydroforth.h new file mode 100644 index 0000000..6debd13 --- /dev/null +++ b/include/hydroforth/hydroforth.h @@ -0,0 +1,59 @@ +#ifndef __HYDROFORTH_H__ +#define __HYDROFORTH_H__ + +#include + +#include "number.h" + +typedef enum HYDROFORTH__WORD_TYPE +{ + PUSH, + CHAR_WORD, + WORD, +} HYDROFORTH__WORD_TYPE; + +typedef union HYDROFORTH__WORD_DATA +{ + int number; + char char_word; + char *word; +} HYDROFORTH__WORD_DATA; + +typedef struct HYDROFORTH__WORD +{ + HYDROFORTH__WORD_TYPE type; + HYDROFORTH__WORD_DATA data; +} HYDROFORTH__WORD; + +typedef struct HYDROFORTH__INTERPRETER +{ + char *src; + unsigned long pos; + HYDROFORTH__WORD call_stack[256]; + unsigned char call_stack_len; + int stack[256]; + unsigned char stack_len; +} HYDROFORTH__INTERPRETER; + +extern bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter); + +extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter); + +typedef struct __HYDROFORTH +{ + __HYDROFORTH__NUMBER number; + bool (*step)(HYDROFORTH__INTERPRETER *interpreter); + bool (*run)(HYDROFORTH__INTERPRETER *interpreter); +} __HYDROFORTH; + +static const __HYDROFORTH hydroforth = { + .number = { + .is_digit = hydroforth__number__is_digit, + .parse_number = hydroforth__number__parse_number, + .parse_number_with_sign = hydroforth__number__parse_number_with_sign, + }, + .step = hydroforth__step, + .run = hydroforth__run, +}; + +#endif diff --git a/include/hydroforth/number.h b/include/hydroforth/number.h new file mode 100644 index 0000000..fab514a --- /dev/null +++ b/include/hydroforth/number.h @@ -0,0 +1,19 @@ +#ifndef __HYDROFORTH__NUMBER_H__ +#define __HYDROFORTH__NUMBER_H__ + +#include + +extern bool hydroforth__number__is_digit(char c); + +extern bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val); + +extern bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val); + +typedef struct __HYDROFORTH__NUMBER +{ + bool (*is_digit)(char c); + bool (*parse_number)(const char *const start, unsigned char len, int *const val); + bool (*parse_number_with_sign)(const char *const start, unsigned char len, int *const val); +} __HYDROFORTH__NUMBER; + +#endif diff --git a/src/hydroforth/hydroforth.c b/src/hydroforth/hydroforth.c new file mode 100644 index 0000000..ba4d05c --- /dev/null +++ b/src/hydroforth/hydroforth.c @@ -0,0 +1,76 @@ +#include +#include + +#include "hydroforth/hydroforth.h" + +bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter) +{ + const unsigned long start = interpreter->pos; + unsigned char len = 0; + while (interpreter->src[interpreter->pos] != ' ' && interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]) + { + len++; + interpreter->pos++; + } + printf("START: %lu\nLEN: %u\n", start, len); + HYDROFORTH__WORD word; + if (len == 1) + { + if (hydroforth__number__is_digit(interpreter->src[start])) + { + word = (HYDROFORTH__WORD){ + .type = PUSH, + .data = {.number = interpreter->src[start] - '0'}, + }; + } + else + { + word = (HYDROFORTH__WORD){ + .type = CHAR_WORD, + .data = {.char_word = interpreter->src[start]}, + }; + } + } + else + { + if ((interpreter->src[start] == '-' || interpreter->src[start] == '+') && + hydroforth__number__is_digit(interpreter->src[start + 1])) + { + } + else if (hydroforth__number__is_digit(interpreter->src[start])) + { + int n; + if (!hydroforth__number__parse_number(interpreter->src + start, len, &n)) + { + printf("RESULT IS FALSE!!!\nNUMBER: %i\n", n); + return false; + } + printf("NUMBER: %i\n", n); + } + else + { + } + } + + return true; +} + +bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter) +{ + while (true) + { + while (interpreter->src[interpreter->pos] == ' ' || interpreter->src[interpreter->pos] == '\n') + { + interpreter->pos++; + } + if (!interpreter->src[interpreter->pos]) + { + puts("END REACHED!"); + return true; + } + if (!hydroforth__step(interpreter)) + { + return false; + } + } +} diff --git a/src/hydroforth/number.c b/src/hydroforth/number.c new file mode 100644 index 0000000..2b1cd42 --- /dev/null +++ b/src/hydroforth/number.c @@ -0,0 +1,49 @@ +#include +#include + +#include "hydroforth/number.h" + +bool hydroforth__number__is_digit(char c) +{ + return '0' <= c && c <= '9'; +} + +bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val) +{ + int num; + if (start[0] == '0') + { + if (len > 1) + { + switch (start[1]) + { + case 'X': + case 'x': + return false; + + default: + return hydroforth__number__parse_number(start + 1, len - 1, val); + } + } + else + { + *val = 0; + return true; + } + } + else + { + int n = start[0] - '0'; + for (unsigned char i = 1; i < len; i++) + { + n *= 10; + n += start[i] - '0'; + } + *val = n; + return true; + } +} + +bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val) +{ +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..3cffd1f --- /dev/null +++ b/src/main.c @@ -0,0 +1,89 @@ +#include +#include +#include + +#include "hydroforth/hydroforth.h" + +struct ReadSrcResult +{ + bool success; + char *const src; +}; + +struct ReadSrcResult read_src(FILE *fp) +{ + if (fseek(fp, 0L, SEEK_END) != 0) + { + fputs("Error seeking to file end!", stderr); + return (struct ReadSrcResult){ + .success = false, + }; + } + const long bufsize = ftell(fp); + if (bufsize == -1) + { + fputs("Error getting file size!", stderr); + return (struct ReadSrcResult){ + .success = false, + }; + } + char *const src = malloc(sizeof(char) * (bufsize + 1)); + if (fseek(fp, 0L, SEEK_SET) != 0) + { + fputs("Error rewinding file to start!", stderr); + return (struct ReadSrcResult){ + .success = false, + }; + } + const unsigned long new_len = fread(src, sizeof(char), bufsize, fp); + if (ferror(fp) != 0) + { + fputs("Error reading file!", stderr); + return (struct ReadSrcResult){ + .success = false, + }; + } + src[new_len + 1] = '\0'; + + return (struct ReadSrcResult){ + .success = true, + .src = src, + }; +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + fputs("No source file specified!", stderr); + return 1; + } + FILE *fp = fopen(argv[1], "rb"); + if (fp == NULL) + { + fputs("Error opening file!", stderr); + return 1; + } + const struct ReadSrcResult res = read_src(fp); + fclose(fp); + if (res.success) + { + HYDROFORTH__INTERPRETER interpreter = { + .src = res.src, + .pos = 0, + }; + const bool run_res = hydroforth.run(&interpreter); + free(res.src); + if (!run_res) + { + return 1; + } + } + else + { + free(res.src); + return 1; + } + + return 0; +} diff --git a/test.fth b/test.fth new file mode 100644 index 0000000..40e2dbf --- /dev/null +++ b/test.fth @@ -0,0 +1 @@ +40 2 + debug