Update
This commit is contained in:
parent
2a9968c4ce
commit
d8cff2488a
7 changed files with 230 additions and 21 deletions
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.lock": "yarnlock",
|
||||||
|
".shards.info": "yaml",
|
||||||
|
".graphqlconfig": "json",
|
||||||
|
"stdbool.h": "c"
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,17 @@ cmake_minimum_required(VERSION 3.22.1)
|
||||||
|
|
||||||
project(hydroforth)
|
project(hydroforth)
|
||||||
|
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT supported OUTPUT error)
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.c)
|
file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.c)
|
||||||
add_executable(hydroforth ${SOURCES})
|
add_executable(hydroforth ${SOURCES})
|
||||||
|
|
||||||
|
if( supported )
|
||||||
|
message(STATUS "IPO / LTO enabled")
|
||||||
|
set_property(TARGET hydroforth PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
else()
|
||||||
|
message(STATUS "IPO / LTO not supported: <${error}>")
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(hydroforth PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(hydroforth PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "number.h"
|
#include "number.h"
|
||||||
|
|
||||||
|
extern unsigned int hydroforth__hash_string(const char *const key, unsigned char length);
|
||||||
|
|
||||||
typedef enum HYDROFORTH__WORD_TYPE
|
typedef enum HYDROFORTH__WORD_TYPE
|
||||||
{
|
{
|
||||||
PUSH,
|
PUSH,
|
||||||
|
@ -25,34 +27,69 @@ typedef struct HYDROFORTH__WORD
|
||||||
HYDROFORTH__WORD_DATA data;
|
HYDROFORTH__WORD_DATA data;
|
||||||
} HYDROFORTH__WORD;
|
} HYDROFORTH__WORD;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__WORD_DEFINITION
|
||||||
|
{
|
||||||
|
HYDROFORTH__WORD *words;
|
||||||
|
} HYDROFORTH__WORD_DEFINITION;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__WORD_DEFINITION_BASE_KEY
|
||||||
|
{
|
||||||
|
unsigned char word_definition_index;
|
||||||
|
} HYDROFORTH__WORD_DEFINITION_BASE_KEY;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
HYDROFORTH__WORD_DEFINITION_BASE_KEY key;
|
||||||
|
} HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY;
|
||||||
|
|
||||||
|
typedef struct HYDROFORTH__WORD_DEFINITION_WORD_KEY
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
HYDROFORTH__WORD_DEFINITION_BASE_KEY key;
|
||||||
|
} HYDROFORTH__WORD_DEFINITION_WORD_KEY;
|
||||||
|
|
||||||
typedef struct HYDROFORTH__INTERPRETER
|
typedef struct HYDROFORTH__INTERPRETER
|
||||||
{
|
{
|
||||||
char *src;
|
char *src;
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
|
HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY single_char_word_keys[32];
|
||||||
|
unsigned char single_char_word_keys_len;
|
||||||
|
unsigned short word_keys_len;
|
||||||
|
unsigned short word_keys_max_len;
|
||||||
|
HYDROFORTH__WORD_DEFINITION_WORD_KEY *word_keys;
|
||||||
|
HYDROFORTH__WORD_DEFINITION word_definitions[256];
|
||||||
HYDROFORTH__WORD call_stack[256];
|
HYDROFORTH__WORD call_stack[256];
|
||||||
unsigned char call_stack_len;
|
unsigned char call_stack_len;
|
||||||
int stack[256];
|
int stack[256];
|
||||||
unsigned char stack_len;
|
unsigned char stack_len;
|
||||||
} HYDROFORTH__INTERPRETER;
|
} HYDROFORTH__INTERPRETER;
|
||||||
|
|
||||||
extern bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter);
|
extern bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
|
||||||
|
extern bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
|
||||||
extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter);
|
extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
|
||||||
typedef struct __HYDROFORTH
|
typedef struct __HYDROFORTH
|
||||||
{
|
{
|
||||||
__HYDROFORTH__NUMBER number;
|
__HYDROFORTH__NUMBER number;
|
||||||
bool (*step)(HYDROFORTH__INTERPRETER *interpreter);
|
unsigned int (*hash_string)(const char *const key, unsigned char len);
|
||||||
|
bool (*parse)(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
|
bool (*run_call_stack)(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
bool (*run)(HYDROFORTH__INTERPRETER *interpreter);
|
bool (*run)(HYDROFORTH__INTERPRETER *interpreter);
|
||||||
} __HYDROFORTH;
|
} __HYDROFORTH;
|
||||||
|
|
||||||
static const __HYDROFORTH hydroforth = {
|
static const __HYDROFORTH hydroforth = {
|
||||||
.number = {
|
.number = {
|
||||||
.is_digit = hydroforth__number__is_digit,
|
.is_digit = hydroforth__number__is_digit,
|
||||||
|
.convert_hex_digit = hydroforth__number__convert_hex_digit,
|
||||||
|
.parse_number_hex = hydroforth__number__parse_number_hex,
|
||||||
.parse_number = hydroforth__number__parse_number,
|
.parse_number = hydroforth__number__parse_number,
|
||||||
.parse_number_with_sign = hydroforth__number__parse_number_with_sign,
|
|
||||||
},
|
},
|
||||||
.step = hydroforth__step,
|
.hash_string = hydroforth__hash_string,
|
||||||
|
.parse = hydroforth__parse,
|
||||||
|
.run_call_stack = hydroforth__run_call_stack,
|
||||||
.run = hydroforth__run,
|
.run = hydroforth__run,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,18 @@
|
||||||
|
|
||||||
extern bool hydroforth__number__is_digit(char c);
|
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__convert_hex_digit(char c, unsigned char *const val);
|
||||||
|
|
||||||
extern bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val);
|
extern bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val);
|
||||||
|
|
||||||
|
extern bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val);
|
||||||
|
|
||||||
typedef struct __HYDROFORTH__NUMBER
|
typedef struct __HYDROFORTH__NUMBER
|
||||||
{
|
{
|
||||||
bool (*is_digit)(char c);
|
bool (*is_digit)(char c);
|
||||||
|
bool (*convert_hex_digit)(char c, unsigned char *const val);
|
||||||
|
bool (*parse_number_hex)(const char *const start, unsigned char len, int *const val);
|
||||||
bool (*parse_number)(const char *const start, unsigned char len, int *const val);
|
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;
|
} __HYDROFORTH__NUMBER;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,9 +1,28 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "hydroforth/hydroforth.h"
|
#include "hydroforth/hydroforth.h"
|
||||||
|
|
||||||
bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter)
|
unsigned int hydroforth__hash_string(const char *const key, unsigned char len)
|
||||||
|
{
|
||||||
|
unsigned char i = 0;
|
||||||
|
unsigned int hash = 0;
|
||||||
|
while (i != len)
|
||||||
|
{
|
||||||
|
hash += key[i++];
|
||||||
|
hash += hash << 10;
|
||||||
|
hash ^= hash >> 6;
|
||||||
|
}
|
||||||
|
hash += hash << 3;
|
||||||
|
hash ^= hash >> 11;
|
||||||
|
hash += hash << 15;
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
{
|
{
|
||||||
const unsigned long start = interpreter->pos;
|
const unsigned long start = interpreter->pos;
|
||||||
unsigned char len = 0;
|
unsigned char len = 0;
|
||||||
|
@ -12,7 +31,6 @@ bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
len++;
|
len++;
|
||||||
interpreter->pos++;
|
interpreter->pos++;
|
||||||
}
|
}
|
||||||
printf("START: %lu\nLEN: %u\n", start, len);
|
|
||||||
HYDROFORTH__WORD word;
|
HYDROFORTH__WORD word;
|
||||||
if (len == 1)
|
if (len == 1)
|
||||||
{
|
{
|
||||||
|
@ -33,22 +51,89 @@ bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((interpreter->src[start] == '-' || interpreter->src[start] == '+') &&
|
const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[start + 1]);
|
||||||
hydroforth__number__is_digit(interpreter->src[start + 1]))
|
if (next_is_digit && interpreter->src[start] == '-')
|
||||||
{
|
{
|
||||||
|
int n;
|
||||||
|
if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n))
|
||||||
|
{
|
||||||
|
fputs("Error parsing number!", stderr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = PUSH,
|
||||||
|
.data = {.number = -n},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (next_is_digit && interpreter->src[start] == '+')
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n))
|
||||||
|
{
|
||||||
|
fputs("Error parsing number!", stderr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = PUSH,
|
||||||
|
.data = {.number = n},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else if (hydroforth__number__is_digit(interpreter->src[start]))
|
else if (hydroforth__number__is_digit(interpreter->src[start]))
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
if (!hydroforth__number__parse_number(interpreter->src + start, len, &n))
|
if (!hydroforth__number__parse_number(interpreter->src + start, len, &n))
|
||||||
{
|
{
|
||||||
printf("RESULT IS FALSE!!!\nNUMBER: %i\n", n);
|
fputs("Error parsing number!", stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printf("NUMBER: %i\n", n);
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = PUSH,
|
||||||
|
.data = {.number = n},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *const s = malloc(sizeof(char) * (len + 1));
|
||||||
|
strncpy(s, interpreter->src + start, len);
|
||||||
|
s[len] = '\0';
|
||||||
|
word = (HYDROFORTH__WORD){
|
||||||
|
.type = WORD,
|
||||||
|
.data = {.word = s},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interpreter->call_stack[interpreter->call_stack_len++] = word;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
|
{
|
||||||
|
printf("CALL STACK LEN: %u\n", interpreter->call_stack_len);
|
||||||
|
for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--)
|
||||||
|
{
|
||||||
|
printf("TYPE: %u\n", interpreter->call_stack[i - 1].type);
|
||||||
|
const HYDROFORTH__WORD *word = interpreter->call_stack + i - 1;
|
||||||
|
switch (word->type)
|
||||||
|
{
|
||||||
|
case PUSH:
|
||||||
|
interpreter->stack[interpreter->stack_len++] = word->data.number;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHAR_WORD:
|
||||||
|
switch (word->data.char_word)
|
||||||
|
{
|
||||||
|
case '-':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WORD:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +150,13 @@ bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter)
|
||||||
}
|
}
|
||||||
if (!interpreter->src[interpreter->pos])
|
if (!interpreter->src[interpreter->pos])
|
||||||
{
|
{
|
||||||
puts("END REACHED!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!hydroforth__step(interpreter))
|
if (!hydroforth__parse(interpreter))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!hydroforth__run_call_stack(interpreter))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,73 @@ bool hydroforth__number__is_digit(char c)
|
||||||
return '0' <= c && c <= '9';
|
return '0' <= c && c <= '9';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val)
|
||||||
|
{
|
||||||
|
if (hydroforth__number__is_digit(c))
|
||||||
|
{
|
||||||
|
*val = c - '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'A':
|
||||||
|
case 'a':
|
||||||
|
*val = 0xa;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
*val = 0xb;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
case 'c':
|
||||||
|
*val = 0xc;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
case 'd':
|
||||||
|
*val = 0xd;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
case 'e':
|
||||||
|
*val = 0xe;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
*val = 0xf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for (unsigned char i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
unsigned char m;
|
||||||
|
if (!hydroforth__number__convert_hex_digit(start[i], &m))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
n *= 16;
|
||||||
|
n += m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val)
|
bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val)
|
||||||
{
|
{
|
||||||
int num;
|
|
||||||
if (start[0] == '0')
|
if (start[0] == '0')
|
||||||
{
|
{
|
||||||
if (len > 1)
|
if (len > 1)
|
||||||
|
@ -19,7 +83,7 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len
|
||||||
{
|
{
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'x':
|
case 'x':
|
||||||
return false;
|
return hydroforth__number__parse_number_hex(start + 2, len - 2, val);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return hydroforth__number__parse_number(start + 1, len - 1, val);
|
return hydroforth__number__parse_number(start + 1, len - 1, val);
|
||||||
|
@ -43,7 +107,3 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
|
@ -71,6 +71,9 @@ int main(int argc, char *argv[])
|
||||||
HYDROFORTH__INTERPRETER interpreter = {
|
HYDROFORTH__INTERPRETER interpreter = {
|
||||||
.src = res.src,
|
.src = res.src,
|
||||||
.pos = 0,
|
.pos = 0,
|
||||||
|
.single_char_word_keys_len = 0,
|
||||||
|
.word_keys_len = 0,
|
||||||
|
.word_keys_max_len = 0,
|
||||||
};
|
};
|
||||||
const bool run_res = hydroforth.run(&interpreter);
|
const bool run_res = hydroforth.run(&interpreter);
|
||||||
free(res.src);
|
free(res.src);
|
||||||
|
|
Loading…
Reference in a new issue