From 16117b9a3acad45c7fadf0fb3929512c6aeafb5f Mon Sep 17 00:00:00 2001 From: zongor Date: Thu, 19 Jun 2025 19:02:03 -0400 Subject: [PATCH] add hashmap as macro, Q16.16 -> float (implement later), general cleanup --- src/compiler.c | 136 ++++++++++++++++++++----- src/hashmap.h | 89 ++++++++++++++++ src/main.c | 5 +- src/opcodes.h | 17 +--- src/parser.c | 268 +++++++++++++++++++++---------------------------- src/parser.h | 50 +++++++-- src/vm.c | 162 ++++-------------------------- 7 files changed, 384 insertions(+), 343 deletions(-) create mode 100644 src/hashmap.h diff --git a/src/compiler.c b/src/compiler.c index ef58916..8610b8c 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -61,8 +61,8 @@ Code *demo_add_compile() { memory[99].u = 0; memory[100].u = 5; memory[101].u = 1; - memory[102].q = FLOAT_TO_Q16_16(5.0f); - memory[103].q = FLOAT_TO_Q16_16(5.0f); + memory[102].f = 5.0f; + memory[103].f = 5.0f; return code; } @@ -79,47 +79,137 @@ Code *compile(char *buffer) { memory[0].c[2] = 'r'; memory[0].c[3] = 'e'; - new_Tokenizer(buffer); + initTokenizer(buffer); Token t = nextToken(); do { debug_printToken(t); switch (t.type) { - case TOKEN_PRINT: - case TOKEN_ADD: - case TOKEN_INT: - /* strncpy(number, t.start, t.length); */ - /* number[t.length + 1] = '\0'; */ - /* int i = strtol(number, NULL, 10); */ - /* memory[ptr].i = i; */ - /* break; */ case TOKEN_LEFT_PAREN: + break; case TOKEN_RIGHT_PAREN: + break; case TOKEN_LEFT_BRACE: + break; case TOKEN_RIGHT_BRACE: + break; + case TOKEN_SEMICOLON: + break; case TOKEN_IDENTIFIER: + break; case TOKEN_STRING: + break; case TOKEN_FLOAT: + break; + case TOKEN_U8: + break; + case TOKEN_I8: + break; + case TOKEN_U16: + break; + case TOKEN_I16: + break; + case TOKEN_U64: + break; + case TOKEN_I64: + break; + case TOKEN_INT: + break; case TOKEN_UINT: - case TOKEN_SUB: - case TOKEN_MUL: - case TOKEN_DIV: + break; case TOKEN_FALSE: + break; case TOKEN_TRUE: - case TOKEN_EOF: - case TOKEN_ERROR: - case TOKEN_MOD: - case TOKEN_GT: - case TOKEN_LT: - case TOKEN_EQ: - case TOKEN_GE: - case TOKEN_LE: - case TOKEN_NE: + break; case TOKEN_NULL: + break; + case TOKEN_EOF: + break; + case TOKEN_ERROR: + break; + case TOKEN_ADD: + break; + case TOKEN_SUB: + break; + case TOKEN_MUL: + break; + case TOKEN_DIV: + break; + case TOKEN_MOD: + break; + case TOKEN_GT: + break; + case TOKEN_LT: + break; + case TOKEN_EQ: + break; + case TOKEN_GE: + break; + case TOKEN_LE: + break; + case TOKEN_NE: + break; case TOKEN_AND: + break; case TOKEN_OR: + break; case TOKEN_XOR: + break; case TOKEN_SHIFTRIGHT: + break; case TOKEN_SHIFTLEFT: + break; + case TOKEN_FN: + break; + case TOKEN_TO: + break; + case TOKEN_IN: + break; + case TOKEN_IS: + break; + case TOKEN_AS: + break; + case TOKEN_USE: + break; + case TOKEN_IF: + break; + case TOKEN_ELSE: + break; + case TOKEN_DEFAULT: + break; + case TOKEN_FOR: + break; + case TOKEN_TRY: + break; + case TOKEN_CATCH: + break; + case TOKEN_WHILE: + break; + case TOKEN_DO: + break; + case TOKEN_EXIT: + break; + case TOKEN_SWITCH: + break; + case TOKEN_RETURN: + break; + case TOKEN_CONST: + break; + case TOKEN_TYPE: + break; + case TOKEN_THIS: + break; + case TOKEN_YIELD: + break; + case TOKEN_CASE: + break; + case TOKEN_ASSERT: + break; + case TOKEN_BREAK: + break; + case TOKEN_LET: + break; + case TOKEN_PRINT: + break; default: break; } diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 0000000..66248ac --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,89 @@ +#ifndef HASHMAP_H +#define HASHMAP_H + +#include +#include + +char *strdup(const char *s) { + size_t len = strlen(s) + 1; + char *copy = (char*)malloc(len); + if (copy) { + memcpy(copy, s, len); + } + return copy; +} + +#define DEFINE_HASHMAP(StructType, HASHSIZE) \ +unsigned int hash_##StructType(char *s) { \ + unsigned int hashval; \ + for (hashval = 0; *s != '\0'; s++) \ + hashval = *s + 31 * hashval; \ + return hashval % HASHSIZE; \ +} \ +\ +StructType *lookup_##StructType(StructType **map, char *s) { \ + StructType *np; \ + for (np = map[hash_##StructType(s)]; np != NULL; np = np->next) \ + if (strcmp(s, np->keyword) == 0) \ + return np; \ + return NULL; \ +} \ +\ +StructType *put_##StructType(StructType **map, char *keyword, TokenType token) { \ + StructType *np; \ + unsigned int hashval; \ + if ((np = lookup_##StructType(map, keyword)) == NULL) { \ + np = (StructType *)malloc(sizeof(*np)); \ + if (np == NULL || (np->keyword = strdup(keyword)) == NULL) \ + return NULL; \ + hashval = hash_##StructType(keyword); \ + np->next = map[hashval]; \ + map[hashval] = np; \ + } \ + np->token = token; \ + return np; \ +} \ +\ +int delete_##StructType(StructType **map, char *keyword) { \ + unsigned int hashval = hash_##StructType(keyword); \ + StructType *current = map[hashval]; \ + StructType *prev = NULL; \ + while (current) { \ + if (strcmp(current->keyword, keyword) == 0) { \ + if (prev) { \ + prev->next = current->next; \ + } else { \ + map[hashval] = current->next; \ + } \ + free(current->keyword); \ + free(current); \ + return 1; \ + } \ + prev = current; \ + current = current->next; \ + } \ + return 0; \ +} \ +\ +StructType **new_##StructType() { \ + StructType **map = (StructType **)calloc(HASHSIZE, sizeof(StructType *)); \ + if (!map) return NULL; \ + return map; \ +} \ +\ +void free_##StructType(StructType **map) { \ + if (!map) return; \ + int i; \ + for (i = 0; i < HASHSIZE; i++) { \ + StructType *current = map[i]; \ + while (current) { \ + StructType *next = current->next; \ + free(current->keyword); \ + free(current); \ + current = next; \ + } \ + } \ + free(map); \ +} + +#endif diff --git a/src/main.c b/src/main.c index 14d55eb..97af7e5 100644 --- a/src/main.c +++ b/src/main.c @@ -52,8 +52,9 @@ int main(int argc, char **argv) { close(sp); } - new_TokenMap(); - code = compile(buffer); + initTokenMap(); + compile(buffer); + code = demo_add_compile(); #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(mainloop, 0, 1); diff --git a/src/opcodes.h b/src/opcodes.h index 8056d78..84962c7 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -5,7 +5,7 @@ typedef union { int32_t i; /* Integers */ - int32_t q; /* Q16.16 (32-bit fixed-point) */ + float f; /* Float */ uint32_t u; /* Unsigned integers */ char c[4]; /* 4 Byte char array for string packing */ } Word; @@ -42,7 +42,7 @@ typedef enum { OP_JLT_REAL, /* jump to address dest if src1 as real < src2 as real */ OP_JLE_REAL, /* jump to address dest if src1 as real <= src2 as real */ OP_REAL_TO_INT, /* dest = src1 as int */ - OP_REAL_TO_UINT, /* dest = src1 as int */ + OP_REAL_TO_UINT, /* dest = src1 as uint */ OP_MOV, /* dest = src1 */ OP_JMP, /* jump to address src1 unconditionally */ OP_INT_TO_STRING, /* dest = src1 as str */ @@ -50,18 +50,7 @@ typedef enum { OP_REAL_TO_STRING, /* dest = src1 as str */ OP_READ_STRING, /* dest = read as str */ OP_PRINT_STRING, /* write src1 to stdout */ - OP_CMP_STRING, /* dest = src1 as str == src2 as str */ + OP_CMP_STRING, /* dest = (str == src2) as bool */ } Opcode; -/* Constants for Q16.16 */ -#define Q16_16_SCALE (1 << 16) -#define Q16_16_SCALE_FLOAT 65536.0f -#define Q16_16_FRACTION_MASK 0x0000FFFF -#define Q16_16_INT_MASK 0xFFFF0000 - -/* Convert float to Q16.16 (with rounding) */ -#define FLOAT_TO_Q16_16(f) ((int32_t)((f) * Q16_16_SCALE_FLOAT + 0.5f)) -/* Convert Q16.16 to float */ -#define Q16_16_TO_FLOAT(q) ((float)(q) / Q16_16_SCALE_FLOAT) - #endif diff --git a/src/parser.c b/src/parser.c index 2b99d8f..da1eea6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,74 +1,63 @@ #include "parser.h" +#include "hashmap.h" -#define HASHSIZE 150 -static TokenMap *hashtab_Token[HASHSIZE]; +DEFINE_HASHMAP(TokenMap, 150); -unsigned int hash_Token(char *s) { - unsigned int hashval; - for (hashval = 0; *s != '\0'; s++) - hashval = *s + 31 * hashval; - return hashval % HASHSIZE; -} +TokenMap **tokenMap; -TokenMap *lookup_Token(char *s) { - TokenMap *np; - for (np = hashtab_Token[hash_Token(s)]; np != NULL; np = np->next) - if (strcmp(s, np->keyword) == 0) - return np; - return NULL; +void initTokenMap() { + tokenMap = new_TokenMap(); + + put_TokenMap(tokenMap, "fn", TOKEN_FN); + put_TokenMap(tokenMap, "to", TOKEN_TO); + put_TokenMap(tokenMap, "in", TOKEN_IN); + put_TokenMap(tokenMap, "is", TOKEN_IS); + put_TokenMap(tokenMap, "as", TOKEN_AS); + put_TokenMap(tokenMap, "use", TOKEN_USE); + put_TokenMap(tokenMap, "if", TOKEN_IF); + put_TokenMap(tokenMap, "else", TOKEN_ELSE); + put_TokenMap(tokenMap, "default", TOKEN_DEFAULT); + put_TokenMap(tokenMap, "for", TOKEN_FOR); + put_TokenMap(tokenMap, "try", TOKEN_TRY); + put_TokenMap(tokenMap, "catch", TOKEN_CATCH); + put_TokenMap(tokenMap, "while", TOKEN_WHILE); + put_TokenMap(tokenMap, "do", TOKEN_DO); + put_TokenMap(tokenMap, "exit", TOKEN_EXIT); + put_TokenMap(tokenMap, "switch", TOKEN_SWITCH); + put_TokenMap(tokenMap, "return", TOKEN_RETURN); + put_TokenMap(tokenMap, "const", TOKEN_CONST); + put_TokenMap(tokenMap, "type", TOKEN_TYPE); + put_TokenMap(tokenMap, "this", TOKEN_THIS); + put_TokenMap(tokenMap, "yield", TOKEN_YIELD); + put_TokenMap(tokenMap, "case", TOKEN_CASE); + put_TokenMap(tokenMap, "assert", TOKEN_ASSERT); + put_TokenMap(tokenMap, "break", TOKEN_BREAK); + put_TokenMap(tokenMap, "let", TOKEN_LET); + put_TokenMap(tokenMap, "print", TOKEN_PRINT); + put_TokenMap(tokenMap, "nil", TOKEN_NULL); + put_TokenMap(tokenMap, "and", TOKEN_AND); + put_TokenMap(tokenMap, "or", TOKEN_OR); + put_TokenMap(tokenMap, "xor", TOKEN_XOR); + put_TokenMap(tokenMap, "mod", TOKEN_MOD); + put_TokenMap(tokenMap, "eq", TOKEN_EQ); + put_TokenMap(tokenMap, "ge", TOKEN_GE); + put_TokenMap(tokenMap, "lt", TOKEN_LT); + put_TokenMap(tokenMap, "le", TOKEN_LE); + put_TokenMap(tokenMap, "ne", TOKEN_NE); + put_TokenMap(tokenMap, "gt", TOKEN_GT); + put_TokenMap(tokenMap, "ge", TOKEN_GE); + put_TokenMap(tokenMap, "srl", TOKEN_SHIFTRIGHT); + put_TokenMap(tokenMap, "sll", TOKEN_SHIFTLEFT); } TokenType get_Token(char *s) { TokenMap *np; - for (np = hashtab_Token[hash_Token(s)]; np != NULL; np = np->next) + for (np = tokenMap[hash_TokenMap(s)]; np != NULL; np = np->next) if (strcmp(s, np->keyword) == 0) return np->token; return TOKEN_IDENTIFIER; } -char *strdup(const char *s) { - size_t len = strlen(s) + 1; - char *copy = malloc(len); - if (copy) { - memcpy(copy, s, len); - } - return copy; -} - -TokenMap *put_Token(char *keyword, TokenType token) { - TokenMap *np; - unsigned int hashval; - if ((np = lookup_Token(keyword)) == NULL) { - np = (TokenMap *)malloc(sizeof(*np)); - if (np == NULL || (np->keyword = strdup(keyword)) == NULL) - return NULL; - hashval = hash_Token(keyword); - np->next = hashtab_Token[hashval]; - hashtab_Token[hashval] = np; - } - np->token = token; - return np; -} - -void new_TokenMap() { - put_Token("nil", TOKEN_NULL); - put_Token("and", TOKEN_AND); - put_Token("or", TOKEN_OR); - put_Token("xor", TOKEN_XOR); - put_Token("mod", TOKEN_MOD); - put_Token("eq", TOKEN_EQ); - put_Token("ge", TOKEN_GE); - put_Token("lt", TOKEN_LT); - put_Token("le", TOKEN_LE); - put_Token("ne", TOKEN_NE); - put_Token("gt", TOKEN_GT); - put_Token("ge", TOKEN_GE); - put_Token("srl", TOKEN_SHIFTRIGHT); - put_Token("sll", TOKEN_SHIFTLEFT); - put_Token("int", TOKEN_INT); - put_Token("print", TOKEN_PRINT); -} - typedef struct Tokenizer Tokenizer; struct Tokenizer { char *start; @@ -78,7 +67,7 @@ struct Tokenizer { Tokenizer tokenizer; -void new_Tokenizer(char *src) { +void initTokenizer(char *src) { tokenizer.start = src; tokenizer.current = src; tokenizer.line = 1; @@ -244,102 +233,71 @@ void debug_printToken(Token t) { char *str = currentTokenToS(); switch (t.type) { - case TOKEN_LEFT_PAREN: - printf("TOKEN_LEFT_PAREN %s line_no=%d\n", str, t.line); - break; - case TOKEN_RIGHT_PAREN: - printf("TOKEN_RIGHT_PAREN %s line_no=%d\n", str, t.line); - break; - case TOKEN_LEFT_BRACE: - printf("TOKEN_LEFT_BRACE %s line_no=%d\n", str, t.line); - break; - case TOKEN_RIGHT_BRACE: - printf("TOKEN_RIGHT_BRACE %s line_no=%d\n", str, t.line); - break; - case TOKEN_IDENTIFIER: - printf("TOKEN_IDENTIFIER %s line_no=%d\n", str, t.line); - break; - case TOKEN_STRING: - printf("TOKEN_STRING %s line_no=%d\n", str, t.line); - break; - case TOKEN_FLOAT: - printf("TOKEN_FLOAT %s line_no=%d\n", str, t.line); - break; - case TOKEN_ERROR: - printf("TOKEN_ERROR %s line_no=%d\n", str, t.line); - break; - case TOKEN_FALSE: - printf("TOKEN_FALSE %s line_no=%d\n", str, t.line); - break; - case TOKEN_TRUE: - printf("TOKEN_TRUE %s line_no=%d\n", str, t.line); - break; - case TOKEN_EOF: - printf("TOKEN_EOF %s line_no=%d\n", str, t.line); - break; - case TOKEN_ADD: - printf("TOKEN_ADD %s line_no=%d\n", str, t.line); - break; - case TOKEN_SUB: - printf("TOKEN_SUB %s line_no=%d\n", str, t.line); - break; - case TOKEN_MUL: - printf("TOKEN_MUL %s line_no=%d\n", str, t.line); - break; - case TOKEN_DIV: - printf("TOKEN_DIV %s line_no=%d\n", str, t.line); - break; - case TOKEN_MOD: - printf("TOKEN_MOD %s line_no=%d\n", str, t.line); - break; - case TOKEN_INT: - printf("TOKEN_INT %s line_no=%d\n", str, t.line); - break; - case TOKEN_UINT: - printf("TOKEN_UINT %s line_no=%d\n", str, t.line); - break; - case TOKEN_SHIFTRIGHT: - printf("TOKEN_SHIFTRIGHT %s line_no=%d\n", str, t.line); - break; - case TOKEN_SHIFTLEFT: - printf("TOKEN_SHIFTLEFT %s line_no=%d\n", str, t.line); - break; - case TOKEN_GT: - printf("TOKEN_GT %s line_no=%d\n", str, t.line); - break; - case TOKEN_LT: - printf("TOKEN_LT %s line_no=%d\n", str, t.line); - break; - case TOKEN_EQ: - printf("TOKEN_EQ %s line_no=%d\n", str, t.line); - break; - case TOKEN_GE: - printf("TOKEN_GE %s line_no=%d\n", str, t.line); - break; - case TOKEN_LE: - printf("TOKEN_LE %s line_no=%d\n", str, t.line); - break; - case TOKEN_NE: - printf("TOKEN_NE %s line_no=%d\n", str, t.line); - break; - case TOKEN_NULL: - printf("TOKEN_NULL %s line_no=%d\n", str, t.line); - break; - case TOKEN_AND: - printf("TOKEN_AND %s line_no=%d\n", str, t.line); - break; - case TOKEN_OR: - printf("TOKEN_OR %s line_no=%d\n", str, t.line); - break; - case TOKEN_XOR: - printf("TOKEN_XOR %s line_no=%d\n", str, t.line); - break; - case TOKEN_SEMICOLON: - printf("TOKEN_SEMICOLON %s line_no=%d\n", str, t.line); - break; - case TOKEN_PRINT: - printf("TOKEN_PRINT %s line_no=%d\n", str, t.line); - break; + PRINT_TOKEN_CASE(TOKEN_LEFT_PAREN) + PRINT_TOKEN_CASE(TOKEN_RIGHT_PAREN) + PRINT_TOKEN_CASE(TOKEN_LEFT_BRACE) + PRINT_TOKEN_CASE(TOKEN_RIGHT_BRACE) + PRINT_TOKEN_CASE(TOKEN_SEMICOLON) + PRINT_TOKEN_CASE(TOKEN_IDENTIFIER) + PRINT_TOKEN_CASE(TOKEN_STRING) + PRINT_TOKEN_CASE(TOKEN_FLOAT) + PRINT_TOKEN_CASE(TOKEN_U8) + PRINT_TOKEN_CASE(TOKEN_I8) + PRINT_TOKEN_CASE(TOKEN_U16) + PRINT_TOKEN_CASE(TOKEN_I16) + PRINT_TOKEN_CASE(TOKEN_U64) + PRINT_TOKEN_CASE(TOKEN_I64) + PRINT_TOKEN_CASE(TOKEN_INT) + PRINT_TOKEN_CASE(TOKEN_UINT) + /* PRINT_TOKEN_CASE(TOKEN_ARRAY) */ + /* PRINT_TOKEN_CASE(TOKEN_MAP) */ + PRINT_TOKEN_CASE(TOKEN_FALSE) + PRINT_TOKEN_CASE(TOKEN_TRUE) + PRINT_TOKEN_CASE(TOKEN_NULL) + PRINT_TOKEN_CASE(TOKEN_EOF) + PRINT_TOKEN_CASE(TOKEN_ERROR) + PRINT_TOKEN_CASE(TOKEN_ADD) + PRINT_TOKEN_CASE(TOKEN_SUB) + PRINT_TOKEN_CASE(TOKEN_MUL) + PRINT_TOKEN_CASE(TOKEN_DIV) + PRINT_TOKEN_CASE(TOKEN_MOD) + PRINT_TOKEN_CASE(TOKEN_GT) + PRINT_TOKEN_CASE(TOKEN_LT) + PRINT_TOKEN_CASE(TOKEN_EQ) + PRINT_TOKEN_CASE(TOKEN_GE) + PRINT_TOKEN_CASE(TOKEN_LE) + PRINT_TOKEN_CASE(TOKEN_NE) + PRINT_TOKEN_CASE(TOKEN_AND) + PRINT_TOKEN_CASE(TOKEN_OR) + PRINT_TOKEN_CASE(TOKEN_XOR) + PRINT_TOKEN_CASE(TOKEN_SHIFTRIGHT) + PRINT_TOKEN_CASE(TOKEN_SHIFTLEFT) + PRINT_TOKEN_CASE(TOKEN_FN) + PRINT_TOKEN_CASE(TOKEN_TO) + PRINT_TOKEN_CASE(TOKEN_IN) + PRINT_TOKEN_CASE(TOKEN_IS) + PRINT_TOKEN_CASE(TOKEN_AS) + PRINT_TOKEN_CASE(TOKEN_USE) + PRINT_TOKEN_CASE(TOKEN_IF) + PRINT_TOKEN_CASE(TOKEN_ELSE) + PRINT_TOKEN_CASE(TOKEN_DEFAULT) + PRINT_TOKEN_CASE(TOKEN_FOR) + PRINT_TOKEN_CASE(TOKEN_TRY) + PRINT_TOKEN_CASE(TOKEN_CATCH) + PRINT_TOKEN_CASE(TOKEN_WHILE) + PRINT_TOKEN_CASE(TOKEN_DO) + PRINT_TOKEN_CASE(TOKEN_EXIT) + PRINT_TOKEN_CASE(TOKEN_SWITCH) + PRINT_TOKEN_CASE(TOKEN_RETURN) + PRINT_TOKEN_CASE(TOKEN_CONST) + PRINT_TOKEN_CASE(TOKEN_TYPE) + PRINT_TOKEN_CASE(TOKEN_THIS) + PRINT_TOKEN_CASE(TOKEN_YIELD) + PRINT_TOKEN_CASE(TOKEN_CASE) + PRINT_TOKEN_CASE(TOKEN_ASSERT) + PRINT_TOKEN_CASE(TOKEN_BREAK) + PRINT_TOKEN_CASE(TOKEN_LET) + PRINT_TOKEN_CASE(TOKEN_PRINT) } free(str); } diff --git a/src/parser.h b/src/parser.h index 4b5ec15..32decf6 100644 --- a/src/parser.h +++ b/src/parser.h @@ -16,15 +16,22 @@ typedef enum TokenType TOKEN_IDENTIFIER, TOKEN_STRING, TOKEN_FLOAT, + TOKEN_U8, + TOKEN_I8, + TOKEN_U16, + TOKEN_I16, + TOKEN_U64, + TOKEN_I64, TOKEN_INT, TOKEN_UINT, /* TOKEN_ARRAY, */ /* TOKEN_MAP, */ TOKEN_FALSE, TOKEN_TRUE, + TOKEN_NULL, TOKEN_EOF, TOKEN_ERROR, - /* Keywords */ + /* Operators */ TOKEN_ADD, TOKEN_SUB, TOKEN_MUL, @@ -36,15 +43,45 @@ typedef enum TokenType TOKEN_GE, TOKEN_LE, TOKEN_NE, - TOKEN_NULL, TOKEN_AND, TOKEN_OR, TOKEN_XOR, TOKEN_SHIFTRIGHT, TOKEN_SHIFTLEFT, + /* Keywords */ + TOKEN_FN, + TOKEN_TO, + TOKEN_IN, + TOKEN_IS, + TOKEN_AS, + TOKEN_USE, + TOKEN_IF, + TOKEN_ELSE, + TOKEN_DEFAULT, + TOKEN_FOR, + TOKEN_TRY, + TOKEN_CATCH, + TOKEN_WHILE, + TOKEN_DO, + TOKEN_EXIT, + TOKEN_SWITCH, + TOKEN_RETURN, + TOKEN_CONST, + TOKEN_TYPE, + TOKEN_THIS, + TOKEN_YIELD, + TOKEN_CASE, + TOKEN_ASSERT, + TOKEN_BREAK, + TOKEN_LET, TOKEN_PRINT, } TokenType; +#define PRINT_TOKEN_CASE(token_suffix) \ + case token_suffix: \ + printf("" #token_suffix " %s line_no=%d\n", str, t.line); \ + break; + typedef struct Token Token; struct Token { @@ -70,13 +107,8 @@ struct TokenMap TokenType token; }; -unsigned int hash_Token(char* s); -TokenMap* lookup_Token(char* s); -TokenType get_Token(char* s); -TokenMap* put_Token(char* keyword, TokenType token); - -void new_Tokenizer (char *src); -void new_TokenMap (); +void initTokenMap(); +void initTokenizer (char *src); void debug_printToken (Token t); Token nextToken(); diff --git a/src/vm.c b/src/vm.c index a40eb3e..49713da 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,10 +1,5 @@ #include "vm.h" -#define MAX_LEN_INT32 11 -#define MAX_INT32 2147483647 -#define MIN_INT32 -2147483648 -const char radix_set[11] = "0123456789"; - #define COMPARE_AND_JUMP(type, accessor, op) \ do { \ type value = memory[src1_addr].accessor; \ @@ -70,76 +65,27 @@ uint32_t step_vm(Word *memory, uint32_t memory_size, uint32_t pc) { case OP_DIV_UINT: MATH_OP(u, /); case OP_ADD_REAL: - MATH_OP(q, +); + MATH_OP(f, +); case OP_SUB_REAL: - MATH_OP(q, -); - case OP_MUL_REAL: { - int32_t a = memory[src1_addr].q; - int32_t b = memory[src2_addr].q; - /* Extract integer and fractional parts */ - int32_t a_int = a & Q16_16_INT_MASK; - int32_t a_frac = a & Q16_16_FRACTION_MASK; - int32_t b_int = b & Q16_16_INT_MASK; - int32_t b_frac = b & Q16_16_FRACTION_MASK; - - /* Compute terms with explicit casting to prevent overflow */ - int32_t term1 = a_int * b_int; /* Integer * Integer */ - int32_t term2 = a_int * b_frac; /* Integer * Fractional */ - int32_t term3 = a_frac * b_int; /* Fractional * Integer */ - int32_t term4 = a_frac * b_frac; /* Fractional * Fractional */ - - /* Scale terms back to Q16.16 (avoid shifting negative values) */ - int32_t scaled_term1 = term1; - int32_t scaled_term2 = (term2 >> 16); - int32_t scaled_term3 = (term3 >> 16); - int32_t scaled_term4 = (term4 >> 16); /* 16-bit shift for 1/65536 scaling */ - /* Combine scaled terms with overflow checks */ - int32_t result = scaled_term1 + scaled_term2 + scaled_term3 + scaled_term4; - memory[dest_addr].q = result; - return pc; - } - - case OP_DIV_REAL: { - int32_t a = memory[src1_addr].q; - int32_t b = memory[src2_addr].q; - if (b == 0) { - printf("Division by zero error at address %d\n", pc - 4); - return 0; - } - - /* Check for overflow */ - int32_t a_int = a >> 16; - int32_t b_int = b >> 16; - - /* If a_int / b_int would overflow, clamp */ - if (b_int == 0 || (a_int > 0 && b_int < 0 && a_int > (MAX_INT32 / b_int)) || - (a_int < 0 && b_int > 0 && a_int < (MIN_INT32 / b_int))) { - return (a < 0) ? MIN_INT32 : MAX_INT32; - } - - /* Scale numerator and divide */ - int32_t scaled_a = a << 16; - int32_t result = scaled_a / b; - - memory[dest_addr].q = result; - - return pc; - } - + MATH_OP(f, -); + case OP_MUL_REAL: + MATH_OP(f, *); + case OP_DIV_REAL: + MATH_OP(f, /); case OP_REAL_TO_INT: - memory[dest_addr].i = (int32_t)(memory[src1_addr].q >> 16); + memory[dest_addr].i = (int32_t)(memory[src1_addr].f); return pc; case OP_INT_TO_REAL: - memory[dest_addr].q = (int32_t)(memory[src1_addr].i << 16); + memory[dest_addr].f = (float)(memory[src1_addr].i); return pc; case OP_REAL_TO_UINT: - memory[dest_addr].u = (int32_t)(memory[src1_addr].q >> 16); + memory[dest_addr].u = (uint32_t)(memory[src1_addr].f); return pc; case OP_UINT_TO_REAL: - memory[dest_addr].q = (uint32_t)(memory[src1_addr].u << 16); + memory[dest_addr].f = (float)(memory[src1_addr].u); return pc; case OP_MOV: @@ -194,88 +140,24 @@ uint32_t step_vm(Word *memory, uint32_t memory_size, uint32_t pc) { COMPARE_AND_JUMP(int32_t, u, <=); } case OP_INT_TO_STRING: { - int32_t v = memory[src1_addr].i; - char buffer[MAX_LEN_INT32]; - int32_t n = v; - bool neg = n < 0; - if (neg) - n = -n; - int i = MAX_LEN_INT32; - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while (n > 0); - if (neg) - buffer[--i] = '-'; - /* Ensure at least one digit is written for 0 */ - if (v == 0) - buffer[--i] = '0'; - /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ - mem_strcpy(memory, buffer + i, MAX_LEN_INT32 - i, dest_addr); + int32_t a = (int32_t)memory[src1_addr].i; + char buffer[32]; + int len = sprintf(buffer, "%d", a); + mem_strcpy(memory, buffer, len, dest_addr); return pc; } case OP_UINT_TO_STRING: { - uint32_t v = memory[src1_addr].u; - char buffer[MAX_LEN_INT32]; - uint32_t n = v; - int i = MAX_LEN_INT32; - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while (n > 0); - /* Ensure at least one digit is written for 0 */ - if (v == 0) - buffer[--i] = '0'; - /* Copy from buffer[i] to buffer + MAX_LEN_INT32 */ - mem_strcpy(memory, buffer + i, MAX_LEN_INT32 - i, dest_addr); + uint32_t a = (uint32_t)memory[src1_addr].u; + char buffer[32]; + int len = sprintf(buffer, "%d", a); + mem_strcpy(memory, buffer, len, dest_addr); return pc; } case OP_REAL_TO_STRING: { - int32_t q = memory[src1_addr].q; - char buffer[32]; /* Max 10 digits for integer part + 6 for fractional + sign - + '.' + null */ - int i = 0, j = 0; - - /* Handle negative numbers */ - if (q < 0) { - buffer[i++] = '-'; - q = -q; - } - - /* Extract integer part (top 16 bits) */ - uint32_t int_part = q >> 16; - /* Extract fractional part (bottom 16 bits) */ - uint32_t frac_part = q & 0xFFFF; - - /* Convert integer part to string (reverse order) */ - if (int_part == 0) { - buffer[i++] = radix_set[0]; - } else { - char tmp[16]; - int tmp_i = 0; - while (int_part > 0) { - tmp[tmp_i++] = radix_set[int_part % 10]; - int_part /= 10; - } - while (tmp_i > 0) { - buffer[i++] = tmp[--tmp_i]; - } - } - - /* Convert fractional part to 6 decimal digits */ - buffer[i++] = '.'; - for (j = 0; j < 6; j++) { - frac_part *= 10; - buffer[i++] = - radix_set[frac_part >> 16]; /* Get integer part of (frac_part * 10) */ - frac_part &= 0xFFFF; /* Keep fractional part for next digit */ - } - - /* Null-terminate */ - buffer[i] = '\0'; - - /* Copy to memory */ - mem_strcpy(memory, buffer, i, dest_addr); + float a = (float)memory[src1_addr].f; + char buffer[32]; + int len = sprintf(buffer, "%f", a); + mem_strcpy(memory, buffer, len, dest_addr); return pc; } case OP_READ_STRING: {