This commit is contained in:
Joseph Kogut 2014-06-08 16:38:38 -07:00
commit ca762c48ad
12 changed files with 182 additions and 25 deletions

2
README
View file

@ -9,3 +9,5 @@ Building can be accomplished using "make," or "make rebuild".
To build a debug version, add "DEBUG=yes" after "make". To build a binary with To build a debug version, add "DEBUG=yes" after "make". To build a binary with
profiling enabled, add "PROFILE=yes" after "make". profiling enabled, add "PROFILE=yes" after "make".
I can be reached at "joseph.kogut(at)gmail.com"

12
SYNTAX
View file

@ -78,9 +78,17 @@ Labels must be specified at the beginning of a line or on their own line.
// 4. PREPROCESSOR /////////////////////////////// // 4. PREPROCESSOR ///////////////////////////////
////////////////////////////////////////////////// //////////////////////////////////////////////////
TVM has a preprocessor that allows other source files to be included with the directive "%include filename.vm" TVM's preprocessor works similarly to many C compilers and uses the prefix "%".
During preprocessing, the entire included source file is inserted in place of the %include directive in memory. // I. Include //
%include filename
Pastes all of the contents of filename into the source code before interpretting it.
// II. Define //
%define identifier value
Define a constant so that all instances of the string "identifier" will be replaced by "value".
////////////////////////////////////////////////// //////////////////////////////////////////////////
// 5. INSTRUCTION LISTING //////////////////////// // 5. INSTRUCTION LISTING ////////////////////////

2
TODO
View file

@ -14,4 +14,4 @@ TODO:
- C interface - C interface
- C Library written in TVM code - C Library written in TVM code
Please send patches to Joseph Kogut <joseph.kogut@gmail.com> Please send patches to Joseph Kogut <joseph.kogut(at)gmail.com>

View file

@ -8,6 +8,7 @@ typedef struct tvm_htab_node_s
{ {
char *key; char *key;
int value; int value;
void *valptr;
struct tvm_htab_node_s *next; struct tvm_htab_node_s *next;
} tvm_htab_node_t; } tvm_htab_node_t;
@ -22,6 +23,8 @@ tvm_htab_t* htab_create();
void htab_destroy(tvm_htab_t *htab); void htab_destroy(tvm_htab_t *htab);
int htab_add(tvm_htab_t *htab, const char *key, int value); int htab_add(tvm_htab_t *htab, const char *key, int value);
int htab_add_ref(tvm_htab_t *htab, const char *key, const void *valptr, int len);
int htab_find(tvm_htab_t *htab, const char *key); int htab_find(tvm_htab_t *htab, const char *key);
char *htab_find_ref(tvm_htab_t *htab, const char *key);
#endif #endif

View file

@ -4,6 +4,8 @@
#define MAX_ARGS 2 #define MAX_ARGS 2
#define MAX_TOKENS 4 #define MAX_TOKENS 4
#include "tvm_htab.h"
typedef struct tvm_lexer_s typedef struct tvm_lexer_s
{ {
char **source_lines; char **source_lines;
@ -14,6 +16,6 @@ tvm_lexer_t *lexer_create();
void lexer_destroy(tvm_lexer_t *l); void lexer_destroy(tvm_lexer_t *l);
/* Tokenize the character array "source" into lines and tokens */ /* Tokenize the character array "source" into lines and tokens */
void lex(tvm_lexer_t *lexer, char *source); void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines);
#endif #endif

View file

@ -1,6 +1,8 @@
#ifndef TVM_PREPROCESSOR_H_ #ifndef TVM_PREPROCESSOR_H_
#define TVM_PREPROCESSOR_H_ #define TVM_PREPROCESSOR_H_
int tvm_preprocess(char *src, int *src_len); #include "tvm_htab.h"
int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines);
#endif #endif

View file

@ -20,6 +20,8 @@ typedef struct tvm_program_s
int **values; int **values;
int num_values; int num_values;
tvm_htab_t *defines;
tvm_htab_t *label_htab; tvm_htab_t *label_htab;
} tvm_program_t; } tvm_program_t;

View file

@ -25,6 +25,8 @@ void htab_destroy(tvm_htab_t *htab)
while(node) while(node)
{ {
next = node->next; next = node->next;
if(node->valptr)
free(node->valptr);
free(node->key); free(node->key);
free(node); free(node);
node = next; node = next;
@ -65,7 +67,13 @@ static void htab_rehash(tvm_htab_t *orig, unsigned int size)
while(node) while(node)
{ {
next = node->next; next = node->next;
htab_add(new, node->key, node->value); if (node->valptr)
{
htab_add_ref(new, node->key, node->valptr, strlen(node->valptr) + 1);
free(node->valptr);
}
else
htab_add(new, node->key, node->value);
free(node->key); free(node->key);
free(node); free(node);
node = next; node = next;
@ -79,8 +87,13 @@ static void htab_rehash(tvm_htab_t *orig, unsigned int size)
free(new); free(new);
} }
int htab_add(tvm_htab_t *htab, const char *k, int v) static tvm_htab_node_t *htab_add_core(tvm_htab_t *htab, const char *k)
{ {
/* Increase bucket count and rehash if the
load factor is too high */
if((float)++htab->num_nodes / htab->size > HTAB_LOAD_FACTOR)
htab_rehash(htab, htab->num_nodes * 2);
int hash = htab_hash(k, htab->size); int hash = htab_hash(k, htab->size);
tvm_htab_node_t *node = htab->nodes[hash]; tvm_htab_node_t *node = htab->nodes[hash];
tvm_htab_node_t *prev = NULL; tvm_htab_node_t *prev = NULL;
@ -101,33 +114,71 @@ int htab_add(tvm_htab_t *htab, const char *k, int v)
node->key = (char *)calloc((strlen(k) + 1), sizeof(char)); node->key = (char *)calloc((strlen(k) + 1), sizeof(char));
strcpy(node->key, k); strcpy(node->key, k);
node->value = v;
if(prev) prev->next = node; if(prev) prev->next = node;
else htab->nodes[hash] = node; /* root node */ else htab->nodes[hash] = node; /* root node */
node->next = NULL; node->next = NULL;
/* Increase bucket count and rehash if the return node;
load factor is too high */ }
if((float)++htab->num_nodes / htab->size > HTAB_LOAD_FACTOR)
htab_rehash(htab, htab->num_nodes * 2); int htab_add(tvm_htab_t *htab, const char *key, int value)
{
tvm_htab_node_t *node = htab_add_core(htab, key);
if (!node)
return -1;
node->value = value;
return 0; return 0;
} }
int htab_find(tvm_htab_t *htab, const char *key) int htab_add_ref(tvm_htab_t *htab, const char *key, const void *valptr, int len)
{
tvm_htab_node_t *node = htab_add_core(htab, key);
if (!node)
return -1;
node->valptr = calloc(len, sizeof(char));
memcpy(node->valptr, valptr, len);
return 0;
}
static tvm_htab_node_t *htab_find_core(tvm_htab_t *htab, const char *key)
{ {
int hash = htab_hash(key, htab->size); int hash = htab_hash(key, htab->size);
tvm_htab_node_t *node = htab->nodes[hash]; tvm_htab_node_t *node = htab->nodes[hash];
while(node) while (node)
{ {
if(!strcmp(node->key, key)) if(!strcmp(node->key, key))
return node->value; return node;
node = node->next; else
node = node->next;
} }
return -1; return NULL;
} }
int htab_find(tvm_htab_t *htab, const char *key)
{
tvm_htab_node_t *node = htab_find_core(htab, key);
if(!node)
return -1;
return node->value;
}
char *htab_find_ref(tvm_htab_t *htab, const char *key)
{
tvm_htab_node_t *node = htab_find_core(htab, key);
if (!node)
return NULL;
return node->valptr;
}

View file

@ -26,7 +26,7 @@ void lexer_destroy(tvm_lexer_t *lexer)
free(lexer); free(lexer);
} }
void lex(tvm_lexer_t *lexer, char *source) void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines)
{ {
int i, j; int i, j;
char *pToken, *pLine = strtok(source, "\n"); char *pToken, *pLine = strtok(source, "\n");
@ -60,12 +60,16 @@ void lex(tvm_lexer_t *lexer, char *source)
for(j = 0; (pToken && j < MAX_TOKENS); j++) for(j = 0; (pToken && j < MAX_TOKENS); j++)
{ {
lexer->tokens[i][j] = (char *)calloc(1, (strlen(pToken) + 1)); char *token = htab_find_ref(defines, pToken);
strcpy(lexer->tokens[i][j], pToken); token = token ? token : pToken;
lexer->tokens[i][j] = (char *)calloc(1, (strlen(token) + 1));
strcpy(lexer->tokens[i][j], token);
pToken = strtok(NULL, " \t,"); pToken = strtok(NULL, " \t,");
} }
} }
lexer->tokens[i] = NULL; lexer->tokens[i] = NULL;
htab_destroy(defines);
} }

View file

@ -3,7 +3,7 @@
#include <string.h> #include <string.h>
int tvm_preprocess(char *src, int *src_len) int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines)
{ {
char* pp_directive_delimiter = NULL; char* pp_directive_delimiter = NULL;
if((pp_directive_delimiter = strstr(src, "%include"))) if((pp_directive_delimiter = strstr(src, "%include")))
@ -22,7 +22,7 @@ int tvm_preprocess(char *src, int *src_len)
if(!pFile) if(!pFile)
{ {
printf("Unable to open file \"%s\"\n", filename); printf("Unable to open file \"%s\"\n", filename);
return 0; return -1;
} }
free(temp_str); free(temp_str);
@ -48,6 +48,63 @@ int tvm_preprocess(char *src, int *src_len)
*src_len = strlen(src); *src_len = strlen(src);
return 1; return 1;
} }
else if((pp_directive_delimiter = strstr(src, "%define ")))
{
char *begin = pp_directive_delimiter;
char *end = strchr(begin, '\n');
if(!end) return 0;
int offset = strlen("%define ");
if(begin + offset >= end)
{
printf("Define missing arguments.\n");
return -1;
}
int length = (end - (begin + offset));
char tempstr[length + 1];
memset(tempstr, 0, length + 1);
memcpy(tempstr, begin + offset, length);
char *keystr = tempstr;
char *valstr = strchr(tempstr, ' ');
/* If there is a value, seperate the key and value
with a null character. */
if(valstr)
{
*valstr = 0;
valstr += 1;
}
if(!keystr || !valstr)
{
printf("Define missing arguments.\n");
return -1;
}
if(htab_find(defines, keystr) < 0)
htab_add_ref(defines, keystr, valstr, strlen(valstr) + 1);
else
{
printf("Multiple definitions for %s.\n", keystr);
return -1;
}
/* Remove the define line so it is not processed again. */
size_t new_length = *src_len - (end - begin);
size_t first_block_len = begin - src;
size_t second_block_len = (src + *src_len) - end;
memmove(&src[first_block_len], end, second_block_len);
src = realloc(src, sizeof(char) * new_length);
*src_len = new_length;
return 1;
}
return 0; return 0;

View file

@ -8,6 +8,7 @@ tvm_program_t *program_create()
{ {
tvm_program_t *p = (tvm_program_t *)calloc(1, sizeof(tvm_program_t)); tvm_program_t *p = (tvm_program_t *)calloc(1, sizeof(tvm_program_t));
p->label_htab = htab_create(); p->label_htab = htab_create();
p->defines = htab_create();
return p; return p;
} }
@ -54,10 +55,15 @@ pi_interpret:
tvm_fcopy(source, source_length, pFile); tvm_fcopy(source, source_length, pFile);
fclose(pFile); fclose(pFile);
while(tvm_preprocess(source, &source_length)); int err = 0;
while((err = tvm_preprocess(source, &source_length, p->defines)) > 0);
/* The preprocessor encountered a problem. */
if (err < 0)
return 1;
tvm_lexer_t *lexer_ctx = lexer_create(); tvm_lexer_t *lexer_ctx = lexer_create();
lex(lexer_ctx, source); lex(lexer_ctx, source, p->defines);
free(source); free(source);
if(parse_labels(p, (const char ***)lexer_ctx->tokens) != 0) return 1; if(parse_labels(p, (const char ***)lexer_ctx->tokens) != 0) return 1;

View file

@ -0,0 +1,20 @@
%define ONE 1
%define ZERO 0
start:
mov eax, ONE
mov ebx, ZERO
loop: add eax, ebx
add ebx, eax
prn eax
prn ebx
cmp eax, ZERO
jl end
cmp ebx, ZERO
jg loop
end: