hydroforth/src/hydroforth/hydroforth.c
2022-12-23 17:16:29 +01:00

309 lines
9 KiB
C

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "hydroforth/hydroforth.h"
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;
}
inline bool hydroforth__is_space(char c)
{
return c == ' ' || c == '\t';
}
HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter)
{
const unsigned long start = interpreter->pos;
unsigned char len = 0;
while (!hydroforth__is_space(interpreter->src[interpreter->pos]) && interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos])
{
len++;
interpreter->pos++;
}
return (HYDROFORTH__SCAN_NEXT_WORD_RESULT){
.start = start,
.len = len,
};
}
void hydroforth__parse(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{
// const unsigned long start = interpreter->pos;
// unsigned char len = 0;
// while (!hydroforth__is_space(interpreter->src[interpreter->pos]) && interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos])
// {
// len++;
// interpreter->pos++;
// }
const HYDROFORTH__SCAN_NEXT_WORD_RESULT res = hydroforth__scan_next_word(interpreter);
if (res.len == 1)
{
if (hydroforth__number__is_digit(interpreter->src[res.start]))
{
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH,
.data = {.number = interpreter->src[res.start] - '0'},
};
}
else
{
switch (interpreter->src[res.start])
{
case '\\':
do
{
interpreter->pos++;
} while (interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]);
break;
case '(':
while (true)
{
interpreter->pos++;
if (interpreter->src[interpreter->pos] == ')' &&
(hydroforth__is_space(interpreter->src[interpreter->pos + 1]) ||
interpreter->src[interpreter->pos + 1] == '\n' ||
interpreter->src[interpreter->pos + 1] == '\0') ||
interpreter->src[interpreter->pos] == '\n' ||
interpreter->src[interpreter->pos] == '\0')
{
break;
}
}
case ':':
printf("WORD DEFINITION\n");
do
{
interpreter->pos++;
} while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n');
if (!interpreter->src[interpreter->pos])
{
// fputs("Unterminated word definition!\n", stderr);
// return false;
hydroforth__set_func_result(result, ERR_UNTERMINATED_WORD_DEFINITION);
return;
}
if (hydroforth__number__is_digit(interpreter->src[interpreter->pos]))
{
// fputs("Word name cannot be a number!\n", stderr);
// return false;
hydroforth__set_func_result(result, ERR_WORD_NAME_CANT_BE_NUMBER);
return;
}
const HYDROFORTH__SCAN_NEXT_WORD_RESULT name_scan_res = hydroforth__scan_next_word(interpreter);
break;
default:
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = CHAR_WORD,
.data = {.char_word = interpreter->src[res.start]},
};
break;
}
}
}
else
{
const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[res.start + 1]);
if (next_is_digit && interpreter->src[res.start] == '-')
{
int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
if (result->error)
{
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr);
return;
}
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH,
.data = {.number = -n},
};
}
else if (next_is_digit && interpreter->src[res.start] == '+')
{
int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
if (result->error)
{
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr);
return;
}
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH,
.data = {.number = n},
};
}
else if (hydroforth__number__is_digit(interpreter->src[res.start]))
{
int n = hydroforth__number__parse_number(result, interpreter->src + res.start, res.len);
if (result->error)
{
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr);
return;
}
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH,
.data = {.number = n},
};
}
else
{
const unsigned int hash = hydroforth__hash_string(interpreter->src + res.start, res.len);
switch (hash)
{
case 0x4078cde9: // --
do
{
interpreter->pos++;
} while (interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]);
break;
default:
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = WORD,
.data = {.hash = hash},
};
break;
}
}
}
}
void hydroforth__run_call_stack(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{
for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--)
{
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 '-':
interpreter->stack[interpreter->stack_len - 2] -= interpreter->stack[interpreter->stack_len - 1];
interpreter->stack_len--;
break;
case '+':
interpreter->stack[interpreter->stack_len - 2] += interpreter->stack[interpreter->stack_len - 1];
interpreter->stack_len--;
break;
case '*':
interpreter->stack[interpreter->stack_len - 2] *= interpreter->stack[interpreter->stack_len - 1];
interpreter->stack_len--;
break;
case '/':
interpreter->stack[interpreter->stack_len - 2] /= interpreter->stack[interpreter->stack_len - 1];
interpreter->stack_len--;
break;
default:
hydroforth__set_func_result(result, ERR_UNKNOWN_SINGLE_CHAR_WORD);
return;
}
break;
case WORD:
printf("HASH: 0x%x\n", word->data.hash);
switch (word->data.hash)
{
case 0xaddd94c: // debug
const unsigned char left_width = hydroforth__number__count_digits(interpreter->stack_len);
unsigned char right_width = 0;
for (unsigned char i = 0; i < interpreter->stack_len; i++)
{
const unsigned char tmp = hydroforth__number__count_digits(interpreter->stack[i]);
if (tmp > right_width)
{
right_width = tmp;
}
}
for (unsigned char i = 0; i < (2 + left_width + 3 + right_width + 2); i++)
{
putchar('-');
}
putchar('\n');
for (unsigned char i = interpreter->stack_len - 1; i != 0xff; i--)
{
printf("| ");
const unsigned char left_index_width = left_width - hydroforth__number__count_digits(i);
for (unsigned char j = 0; j < left_index_width; j++)
{
putchar(' ');
}
printf("%u | ", i);
const unsigned char right_index_width = right_width - hydroforth__number__count_digits(interpreter->stack[i]);
for (unsigned char j = 0; j < right_index_width; j++)
{
putchar(' ');
}
printf("%i |\n", interpreter->stack[i]);
}
for (unsigned char i = 0; i < (2 + left_width + 3 + right_width + 2); i++)
{
putchar('-');
}
putchar('\n');
break;
default:
hydroforth__set_func_result(result, ERR_UNKNOWN_WORD);
return;
}
break;
}
}
}
void hydroforth__run(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{
while (true)
{
while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n')
{
interpreter->pos++;
}
if (!interpreter->src[interpreter->pos])
{
return;
}
hydroforth__parse(result, interpreter);
if (result->error)
{
hydroforth__add_func_backtrace(result);
return;
}
hydroforth__run_call_stack(result, interpreter);
if (result->error)
{
hydroforth__add_func_backtrace(result);
return;
}
}
}