.
This commit is contained in:
@@ -21,10 +21,10 @@ The bytecode file is composed of the following sections:
|
|||||||
[1..4]: real
|
[1..4]: real
|
||||||
|
|
||||||
* CODE
|
* CODE
|
||||||
|
[0:3]: Debug start address (or zero)
|
||||||
|
[4:7]: Number of functions
|
||||||
Each function:
|
Each function:
|
||||||
[0:3] Address of next function
|
[0:3] Address of next function
|
||||||
[4:5] Number of parameters
|
|
||||||
[6:7] Number of variables
|
|
||||||
[...] Code
|
[...] Code
|
||||||
[0] : Opcode
|
[0] : Opcode
|
||||||
[between 1 and 4] : Operand
|
[between 1 and 4] : Operand
|
||||||
|
|||||||
37
lib/code.c
37
lib/code.c
@@ -1,9 +1,42 @@
|
|||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
Code* code_load_bytecode(uint8_t* bytecode, size_t bytecode_sz)
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct Code {
|
||||||
|
};
|
||||||
|
|
||||||
|
Code* code_new(uint8_t* bytecode, size_t bytecode_sz)
|
||||||
{
|
{
|
||||||
|
Code* code = xcalloc(1, sizeof(Code));
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code* code_load_bytecode_cb(void(*read_bytes)(size_t, void*), void* data)
|
void code_destroy(Code* code)
|
||||||
{
|
{
|
||||||
|
free(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t code_n_consts(Code const* code)
|
||||||
|
{
|
||||||
|
return 0; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
TYC_CONST_TYPE code_const_type(Code const* code, size_t n)
|
||||||
|
{
|
||||||
|
return TC_REAL; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
T_REAL code_const_real(Code const* code, size_t n)
|
||||||
|
{
|
||||||
|
return 0.f; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* code_const_string(Code const* code, size_t n)
|
||||||
|
{
|
||||||
|
return ""; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t code_n_functions(Code const* code)
|
||||||
|
{
|
||||||
|
return 0; // TODO
|
||||||
}
|
}
|
||||||
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
|
||||||
#include "compiler/compiler.lua.h"
|
#include "compiler/compiler.lua.h"
|
||||||
|
|
||||||
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz)
|
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz)
|
||||||
{
|
{
|
||||||
lua_State* L = luaL_newstate();
|
lua_State* L = luaL_newstate();
|
||||||
|
luaL_openlibs(L);
|
||||||
|
|
||||||
int r = luaL_loadbufferx(L, (const char *) lib_compiler_compiler_out, lib_compiler_compiler_out_len, "compiler", "b");
|
int r = luaL_loadbufferx(L, (const char *) lib_compiler_compiler_out, lib_compiler_compiler_out_len, "compiler", "b");
|
||||||
if (r == LUA_ERRSYNTAX)
|
if (r == LUA_ERRSYNTAX)
|
||||||
@@ -18,6 +20,8 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_
|
|||||||
else if (r == LUA_ERRMEM)
|
else if (r == LUA_ERRMEM)
|
||||||
out_of_memory();
|
out_of_memory();
|
||||||
|
|
||||||
|
lua_call(L, 0, 1);
|
||||||
|
|
||||||
lua_pushstring(L, code);
|
lua_pushstring(L, code);
|
||||||
r = lua_pcall(L, 1, 1, 0);
|
r = lua_pcall(L, 1, 1, 0);
|
||||||
if (r == LUA_ERRMEM) {
|
if (r == LUA_ERRMEM) {
|
||||||
@@ -29,7 +33,15 @@ TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_
|
|||||||
return T_ERR_ASSEMBLER_SYNTAX_ERROR;
|
return T_ERR_ASSEMBLER_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lua_istable(L, -1))
|
||||||
|
abort();
|
||||||
|
*bytecode_sz = luaL_len(L, -1);
|
||||||
|
*bytecode = malloc(*bytecode_sz);
|
||||||
|
for (size_t i = 0; i < *bytecode_sz; ++i) {
|
||||||
|
lua_geti(L, -1, i + 1);
|
||||||
|
(*bytecode)[i] = (uint8_t) lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
return T_OK;
|
return T_OK;
|
||||||
|
|||||||
@@ -81,5 +81,6 @@ end
|
|||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
return function(source)
|
return function(source)
|
||||||
|
print('test')
|
||||||
return { 0, 1, 2, 3, 4 }
|
return { 0, 1, 2, 3, 4 }
|
||||||
end
|
end
|
||||||
16
lib/priv.h
16
lib/priv.h
@@ -29,6 +29,10 @@ typedef struct Code Code;
|
|||||||
typedef uint32_t HEAP_KEY;
|
typedef uint32_t HEAP_KEY;
|
||||||
typedef uint64_t TABLE_HASH;
|
typedef uint64_t TABLE_HASH;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TC_STRING, TC_REAL,
|
||||||
|
} TYC_CONST_TYPE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// UTILS
|
// UTILS
|
||||||
//
|
//
|
||||||
@@ -122,9 +126,15 @@ void heap_gc(Heap* h, VALUE const* roots, size_t n_roots);
|
|||||||
|
|
||||||
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz);
|
TYC_RESULT code_assemble(const char* code, uint8_t** bytecode, size_t* bytecode_sz);
|
||||||
|
|
||||||
Code* code_load_bytecode(uint8_t* bytecode, size_t bytecode_sz);
|
Code* code_new(uint8_t* bytecode, size_t bytecode_sz);
|
||||||
Code* code_load_bytecode_cb(void(*read_bytes)(size_t, void*), void* data);
|
|
||||||
|
|
||||||
void code_destroy(Code* code);
|
void code_destroy(Code* code);
|
||||||
|
|
||||||
|
size_t code_n_consts(Code const* code);
|
||||||
|
TYC_CONST_TYPE code_const_type(Code const* code, size_t n);
|
||||||
|
|
||||||
|
T_REAL code_const_real(Code const* code, size_t n);
|
||||||
|
const char* code_const_string(Code const* code, size_t n);
|
||||||
|
|
||||||
|
size_t code_n_functions(Code const* code);
|
||||||
|
|
||||||
#endif //TYCHE_PRIV_H
|
#endif //TYCHE_PRIV_H
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ typedef enum {
|
|||||||
T_ERR_ASSEMBLER_SYNTAX_ERROR = -30,
|
T_ERR_ASSEMBLER_SYNTAX_ERROR = -30,
|
||||||
} TYC_RESULT;
|
} TYC_RESULT;
|
||||||
|
|
||||||
|
#define T_REAL float
|
||||||
|
|
||||||
#endif //TYCHE_TYCHE_H
|
#endif //TYCHE_TYCHE_H
|
||||||
|
|||||||
14
test/code-tests.lua
Normal file
14
test/code-tests.lua
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
return {
|
||||||
|
{
|
||||||
|
name = "VM: basic",
|
||||||
|
code = [[
|
||||||
|
.func 0
|
||||||
|
pushi 2
|
||||||
|
pushi 3
|
||||||
|
sum
|
||||||
|
ret
|
||||||
|
]],
|
||||||
|
expected_stack_size = 1,
|
||||||
|
expected_stack_top = { integer = 5 },
|
||||||
|
},
|
||||||
|
}
|
||||||
31
test/tests.c
31
test/tests.c
@@ -213,4 +213,35 @@ int main()
|
|||||||
heap_destroy(h);
|
heap_destroy(h);
|
||||||
stack_destroy(s);
|
stack_destroy(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
printf("### Bytecode\n");
|
||||||
|
const char* assembly_code =
|
||||||
|
".const\n"
|
||||||
|
" 0: 3.14\n"
|
||||||
|
" 1: \"Hello world\"\n"
|
||||||
|
"\n"
|
||||||
|
".func 0\n"
|
||||||
|
" pushi 2 ; this is a comment\n"
|
||||||
|
" pushi 3\n"
|
||||||
|
" sum\n"
|
||||||
|
" ret\n"
|
||||||
|
".func 1\n"
|
||||||
|
" pushi 5000\n"
|
||||||
|
" ret";
|
||||||
|
|
||||||
|
uint8_t* bytecode; size_t bytecode_sz;
|
||||||
|
assert(code_assemble(assembly_code, &bytecode, &bytecode_sz) == T_OK);
|
||||||
|
|
||||||
|
Code* code = code_new(bytecode, bytecode_sz);
|
||||||
|
|
||||||
|
assert(code_n_consts(code) == 2);
|
||||||
|
assert(code_const_type(code, 0) == TC_REAL);
|
||||||
|
assert(code_const_type(code, 1) == TC_STRING);
|
||||||
|
assert(code_const_real(code, 0) >= 3.13 && code_const_real(code, 0) <= 3.15);
|
||||||
|
assert(strcmp(code_const_string(code, 1), "Hello world\n") == 0);
|
||||||
|
assert(code_n_functions(code) == 2);
|
||||||
|
|
||||||
|
free(bytecode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user