add hashmap as macro, Q16.16 -> float (implement later), general cleanup
This commit is contained in:
parent
fd9516bf7e
commit
16117b9a3a
136
src/compiler.c
136
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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef HASHMAP_H
|
||||
#define HASHMAP_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
268
src/parser.c
268
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);
|
||||
}
|
||||
|
|
50
src/parser.h
50
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();
|
||||
|
||||
|
|
162
src/vm.c
162
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: {
|
||||
|
|
Loading…
Reference in New Issue