.
This commit is contained in:
@@ -40,14 +40,14 @@ void code_destroy(Code* code)
|
||||
free(code);
|
||||
}
|
||||
|
||||
TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz)
|
||||
TYC_RESULT code_load_bytecode(Code* code, uint8_t const* bytecode, size_t bytecode_sz)
|
||||
{
|
||||
// TODO - linking
|
||||
|
||||
if (bytecode_sz < 24)
|
||||
return T_ERR_BYTECODE_TOO_SMALL;
|
||||
|
||||
uint32_t magic = *(uint32_t*) &bytecode[0];
|
||||
uint32_t magic = *(uint32_t const*) &bytecode[0];
|
||||
if (magic != MAGIC)
|
||||
return T_ERR_BYTECODE_INVALID_MAGIC;
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytec
|
||||
Code* code_new(void);
|
||||
void code_destroy(Code* code);
|
||||
|
||||
TYC_RESULT code_load_bytecode(Code* code, uint8_t* bytecode, size_t bytecode_sz);
|
||||
TYC_RESULT code_load_bytecode(Code* code, uint8_t const* bytecode, size_t bytecode_sz);
|
||||
|
||||
uint32_t code_n_consts(Code const* code);
|
||||
TYC_CONST_TYPE code_const_type(Code const* code, size_t n);
|
||||
|
||||
24
lib/tyche.h
24
lib/tyche.h
@@ -1,6 +1,9 @@
|
||||
#ifndef TYCHE_TYCHE_H
|
||||
#define TYCHE_TYCHE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
TT_NIL, TT_INTEGER, TT_REAL, TT_STRING, TT_STRING_CONST, TT_ARRAY, TT_TABLE, TT_FUNCTION, TT_NATIVE_PTR,
|
||||
} TYC_TYPE;
|
||||
@@ -12,8 +15,29 @@ typedef enum {
|
||||
T_ERR_TABLE_KEY_NOT_FOUND = -20,
|
||||
T_ERR_ASSEMBLER_SYNTAX_ERROR = -30,
|
||||
T_ERR_BYTECODE_TOO_SMALL = -40, T_ERR_BYTECODE_INVALID_MAGIC = -41,
|
||||
T_ERR_TYPE_UNEXPECTED = -50,
|
||||
} TYC_RESULT;
|
||||
|
||||
typedef enum {
|
||||
TX_SUM,
|
||||
} TYC_EXPR;
|
||||
|
||||
#define T_REAL float
|
||||
|
||||
typedef struct TycheVM TycheVM;
|
||||
|
||||
// create/destroy VM
|
||||
TycheVM* tyc_new(void);
|
||||
void tyc_destroy(TycheVM* t);
|
||||
|
||||
// code loading and execution
|
||||
TYC_RESULT tyc_load_bytecode(TycheVM* T, uint8_t const* bytecode, size_t bytecode_sz);
|
||||
TYC_RESULT tyc_call(TycheVM* t, uint16_t n_pars);
|
||||
|
||||
// stack manipulation and query
|
||||
void tyc_pushinteger(TycheVM* T, int32_t value);
|
||||
TYC_RESULT tyc_type(TycheVM* T, int idx, TYC_TYPE* type);
|
||||
TYC_RESULT tyc_tointeger(TycheVM* T, int idx, int32_t* value);
|
||||
TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR expr);
|
||||
|
||||
#endif //TYCHE_TYCHE_H
|
||||
|
||||
71
lib/vm.c
71
lib/vm.c
@@ -1 +1,72 @@
|
||||
#include "priv.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
struct TycheVM {
|
||||
Stack* stack;
|
||||
Heap* heap;
|
||||
Code* code;
|
||||
};
|
||||
|
||||
TycheVM* tyc_new(void)
|
||||
{
|
||||
TycheVM* t = xcalloc(1, sizeof(TycheVM));
|
||||
t->stack = stack_new();
|
||||
t->heap = heap_new();
|
||||
t->code = code_new();
|
||||
return t;
|
||||
}
|
||||
|
||||
void tyc_destroy(TycheVM* t)
|
||||
{
|
||||
code_destroy(t->code);
|
||||
heap_destroy(t->heap);
|
||||
stack_destroy(t->stack);
|
||||
free(t);
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_load_bytecode(TycheVM* T, uint8_t const* bytecode, size_t bytecode_sz)
|
||||
{
|
||||
return code_load_bytecode(T->code, bytecode, bytecode_sz);
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_call(TycheVM* T, uint16_t n_pars)
|
||||
{
|
||||
abort(); // TODO
|
||||
}
|
||||
|
||||
void tyc_pushinteger(TycheVM* T, int32_t value)
|
||||
{
|
||||
stack_push(T->stack, create_value_integer(value));
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_type(TycheVM* T, int idx, TYC_TYPE* type)
|
||||
{
|
||||
VALUE v;
|
||||
TYC_RESULT r = stack_at(T->stack, idx, &v);
|
||||
if (r == T_OK)
|
||||
*type = v.type;
|
||||
return r;
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_tointeger(TycheVM* T, int idx, int32_t* value)
|
||||
{
|
||||
VALUE v;
|
||||
TYC_RESULT r = stack_at(T->stack, idx, &v);
|
||||
if (r == T_OK) {
|
||||
if (v.type != TT_INTEGER)
|
||||
return T_ERR_TYPE_UNEXPECTED;
|
||||
*value = value_integer(v);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR expr)
|
||||
{
|
||||
// TODO
|
||||
VALUE v1, v2;
|
||||
stack_pop(T->stack, &v2);
|
||||
stack_pop(T->stack, &v1);
|
||||
stack_push(T->stack, create_value_integer(value_integer(v1) + value_integer(v2)));
|
||||
return T_OK;
|
||||
}
|
||||
@@ -9,6 +9,6 @@ return {
|
||||
ret
|
||||
]],
|
||||
expected_stack_size = 1,
|
||||
expected_stack_top = { integer = 5 },
|
||||
expected_stack_top = 5,
|
||||
},
|
||||
}
|
||||
73
test/tests.c
73
test/tests.c
@@ -6,12 +6,19 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
#define EQ(a, b) (memcmp(a, b) == 0)
|
||||
|
||||
static void run_assembly_tests(void);
|
||||
static void run_assembly_test(lua_State* L);
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
printf("### Values\n");
|
||||
printf("## Values\n");
|
||||
assert(value_type(create_value_integer(42)) == TT_INTEGER);
|
||||
assert(value_integer(create_value_integer(-42)) == -42);
|
||||
assert(fabsf(value_real(create_value_real(42.4f)) - 42.4f) < 0.00001f);
|
||||
@@ -19,7 +26,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Stack\n");
|
||||
printf("## Stack\n");
|
||||
|
||||
Stack* s = stack_new();
|
||||
|
||||
@@ -53,7 +60,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Stack with frame pointer\n");
|
||||
printf("## Stack with frame pointer\n");
|
||||
|
||||
Stack* s = stack_new();
|
||||
|
||||
@@ -92,7 +99,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Arrays\n");
|
||||
printf("## Arrays\n");
|
||||
|
||||
Array* a = array_new();
|
||||
assert(array_len(a) == 0);
|
||||
@@ -114,7 +121,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Table - integer index\n");
|
||||
printf("## Table - integer index\n");
|
||||
|
||||
Heap* h = heap_new();
|
||||
Table* t = table_new(h);
|
||||
@@ -135,7 +142,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Table - string index\n");
|
||||
printf("## Table - string index\n");
|
||||
|
||||
Heap* h = heap_new();
|
||||
Table* t = table_new(h);
|
||||
@@ -162,7 +169,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Heap - strings\n");
|
||||
printf("## Heap - strings\n");
|
||||
|
||||
Heap* h = heap_new();
|
||||
|
||||
@@ -178,7 +185,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Heap - string GC\n");
|
||||
printf("## Heap - string GC\n");
|
||||
|
||||
Stack* s = stack_new();
|
||||
Heap* h = heap_new();
|
||||
@@ -215,7 +222,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Bytecode\n");
|
||||
printf("## Bytecode\n");
|
||||
const char* assembly_code =
|
||||
".const\n"
|
||||
" 0: 3.14\n"
|
||||
@@ -271,7 +278,7 @@ int main()
|
||||
}
|
||||
|
||||
{
|
||||
printf("### Bytecode - labels\n");
|
||||
printf("## Bytecode - labels\n");
|
||||
const char* assembly_code =
|
||||
".func 0\n"
|
||||
" jmp @my_label\n"
|
||||
@@ -293,4 +300,50 @@ int main()
|
||||
code_destroy(code);
|
||||
free(bytecode);
|
||||
}
|
||||
|
||||
{
|
||||
printf("## VM - Basic\n");
|
||||
|
||||
TycheVM* T = tyc_new();
|
||||
|
||||
tyc_pushinteger(T, 2);
|
||||
tyc_pushinteger(T, 3);
|
||||
tyc_expr(T, TX_SUM);
|
||||
int32_t result; assert(tyc_tointeger(T, -1, &result) == T_OK);
|
||||
assert(result == 5);
|
||||
|
||||
tyc_destroy(T);
|
||||
}
|
||||
|
||||
{
|
||||
printf("## Assembly tests\n");
|
||||
run_assembly_tests();
|
||||
}
|
||||
}
|
||||
|
||||
static void run_assembly_tests(void)
|
||||
{
|
||||
lua_State* L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
int r = luaL_loadfile(L, "./test/code-tests.lua");
|
||||
assert(r == LUA_OK);
|
||||
lua_call(L, 0, 1);
|
||||
assert(lua_istable(L, -1));
|
||||
|
||||
int len = luaL_len(L, -1);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
lua_geti(L, -1, i + 1);
|
||||
run_assembly_test(L);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
static void run_assembly_test(lua_State* L)
|
||||
{
|
||||
lua_getfield(L, -1, "name");
|
||||
printf(" - %s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, -1);
|
||||
}
|
||||
Reference in New Issue
Block a user