.
This commit is contained in:
35
lua-temp/doc/BYTECODE
Normal file
35
lua-temp/doc/BYTECODE
Normal file
@@ -0,0 +1,35 @@
|
||||
Bytecode format
|
||||
---------------
|
||||
|
||||
The bytecode file is composed of the following sections:
|
||||
|
||||
* HEADER: 16-byte header
|
||||
[0:3]: Magic
|
||||
[4]: VM format
|
||||
[rest]: Reserved for future use
|
||||
* TABLE_OF_CONTENTS: list of 8 records pointing to each one of the sections
|
||||
Each record (6 bytes):
|
||||
- Pointer to section: 4 bytes
|
||||
- Number of records in section: 2 bytes
|
||||
* [0x0] Constants indexes: pointers to each of the constant locations
|
||||
* Table of 4-byte constant indexes with pointer to constant
|
||||
(counter start at beginning of raw constants)
|
||||
* [0x1] Functions indexes: Pointer to functions within the code
|
||||
[0:3]: function pointer (counter start at the beginning of executable code)
|
||||
[4:5]: number of parameters
|
||||
[6:7]: number of local variables
|
||||
[8:b]: function size
|
||||
* [0x2] Constants raw data
|
||||
* [0x3] Code: executable code
|
||||
* [0x4] Debugging info
|
||||
???
|
||||
|
||||
The max file size is 2 Gb.
|
||||
|
||||
## Values can be encoded in the following ways:
|
||||
* The type is defined by the operator.
|
||||
* Encoding varies according to the type:
|
||||
int: use protobuf format
|
||||
float: 4-bit floating point
|
||||
string: int-defined length, followed by the string proper - no null terminator
|
||||
* Constant indexes and function ids are encoded as ints
|
||||
93
lua-temp/doc/OPCODES
Normal file
93
lua-temp/doc/OPCODES
Normal file
@@ -0,0 +1,93 @@
|
||||
Operations
|
||||
----------
|
||||
|
||||
Operations take either 0 or 1 parameter. The ones that take a parameter, it can be either a int8, int16 or int32.
|
||||
|
||||
Instructions follow this logic:
|
||||
|
||||
00 ~ 9F : no parameter
|
||||
A0 ~ BF : int8 (1 byte)
|
||||
C0 ~ DF : int16 (2 bytes)
|
||||
E0 ~ FF : int32 (4 bytes)
|
||||
|
||||
The operations of 1, 2 and 4 bytes are always interchangeable by adding/subtracting 0x20.
|
||||
|
||||
,----------- no parameter
|
||||
| ,-------- int8
|
||||
| | ,----- int16
|
||||
| | | ,-- int32
|
||||
NP I8 I16 I32 Opc Instruction Description
|
||||
|
||||
Stack operations:
|
||||
a0 c0 e0 pushi [int] Push int
|
||||
a1 c1 e1 pushc [index] Push constant
|
||||
a2 c2 e2 pushf [function] Push function id
|
||||
00 pushz Push zero (or false)
|
||||
01 pusht Push true
|
||||
02 newa Push (create) empty array
|
||||
03 newt Push (create) empty table
|
||||
04 pop
|
||||
05 dup
|
||||
|
||||
Local variables:
|
||||
a3 c3 e3 pushv [int] Push n nil values into the stack (used to init local vars)
|
||||
ab cb eb set [index] Set value in stack position (set local variable)
|
||||
a4 c4 e4 dupv [index] Duplicate stack value (load local variable)
|
||||
a5 c5 e5 setg [int] Set global variable
|
||||
a6 c6 e6 getg [int] Get global variable
|
||||
|
||||
Function operations:
|
||||
a7 c7 e7 call [n_pars] Enter function on stack toplevel (passing n next stack values as parameters)
|
||||
10 ret Leave a function (return value in stack)
|
||||
11 retn Leave a function (return nil)
|
||||
|
||||
Table and array operations:
|
||||
16 getkv Get table's value based on key (pull 1 value, push 1 value)
|
||||
17 setkv Set table's key and value (pull 2 values from stack)
|
||||
18 geta Get array's position value
|
||||
19 seta Set array's position value (pull 2 values from stack)
|
||||
1a appnd Add value to the end of array
|
||||
1b next Push the next pair into the stack (for loops)
|
||||
1c smt Set value metatable
|
||||
1d mt Get value metatable
|
||||
|
||||
Logical/arithmetic:
|
||||
20 sum Sum top 2 values in stack
|
||||
21 sub Subtract top 2 values in stack
|
||||
22 mul Multiply top 2 values in stack
|
||||
23 div Float division
|
||||
24 idiv Integer division
|
||||
25 eq Equality
|
||||
26 neq Inequality
|
||||
27 lt Less than
|
||||
28 lte Less than or equals
|
||||
29 gt Greater than
|
||||
2a gte Greater than or equals
|
||||
2b and Bitwise AND
|
||||
2c or Bitwise OR
|
||||
2d xor Bitwise XOR
|
||||
2e pow Power
|
||||
2f shl Shift left
|
||||
30 shr Shift right
|
||||
31 mod Modulo
|
||||
|
||||
Other value operations:
|
||||
40 len Get table, array or string size
|
||||
41 type Get type from value at the top of the stack
|
||||
b0 cast [type] Cast type to another type
|
||||
42 ver Return VM version
|
||||
|
||||
External code:
|
||||
48 cmpl Compile code to assembly
|
||||
49 asmbl Assemble code to bytecode format
|
||||
4a load Load bytecode as function (will place function on stack)
|
||||
|
||||
Control flow:
|
||||
a8 c8 e8 bz [pc] Branch if zero
|
||||
a9 c9 e9 bnz [pc] Branch if not zero
|
||||
aa ca ea jmp [pc] Unconditional jump
|
||||
* Jumps can only happen within the same function.
|
||||
|
||||
|
||||
Error handling: (0xa0~0xaf)
|
||||
???
|
||||
15
lua-temp/doc/VM
Normal file
15
lua-temp/doc/VM
Normal file
@@ -0,0 +1,15 @@
|
||||
Internal handling of values
|
||||
---------------------------
|
||||
|
||||
## Supported types
|
||||
Nil 0
|
||||
Integer 1
|
||||
Float 2
|
||||
String 3
|
||||
Array 4
|
||||
Table 5
|
||||
Function 6
|
||||
NativePointer 7
|
||||
|
||||
## Internal format
|
||||
???
|
||||
74
lua-temp/tests.lua
Normal file
74
lua-temp/tests.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
local assemble = require('tyche-as')
|
||||
|
||||
function tprint(o, indent)
|
||||
indent = indent or 0
|
||||
local spacing = string.rep(" ", indent)
|
||||
|
||||
if type(o) == 'table' then
|
||||
local s = '{\n'
|
||||
for k, v in pairs(o) do
|
||||
-- Format keys: quote strings, leave numbers as is
|
||||
local key = type(k) == 'string' and '["'..k..'"]' or '['..k..']'
|
||||
s = s .. spacing .. " " .. key .. " = " .. tprint(v, indent + 1) .. ",\n"
|
||||
end
|
||||
return s .. spacing .. '}'
|
||||
elseif type(o) == 'string' then
|
||||
return '"' .. o .. '"'
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
function assert_eq(found, expected, key)
|
||||
assert(type(found) == type(expected), "Types not matching " .. ((key ~= nil) and ('(key: ' .. key .. ')') or ''))
|
||||
if type(found) == 'table' then
|
||||
assert(#found == #expected, "Tables are of different sizes " .. ((key ~= nil) and ('(key: ' .. key .. ')') or ''))
|
||||
for k,v in pairs(found) do
|
||||
assert_eq(v, expected[k], k)
|
||||
end
|
||||
for k,v in pairs(expected) do
|
||||
assert_eq(v, found[k], k)
|
||||
end
|
||||
else
|
||||
assert(found == expected, 'Assertion failed, expected "' .. tprint(expected) .. '", found "' .. tprint(found) .. '".')
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local source = [[
|
||||
.const
|
||||
0: 3.14
|
||||
1: "Hello world"
|
||||
|
||||
.func 0
|
||||
pushi 2 ; this is a comment
|
||||
pushi 3
|
||||
sum
|
||||
ret
|
||||
.func 1
|
||||
pushi 5000
|
||||
ret ]]
|
||||
|
||||
local expected = {
|
||||
constants = { [0] = 3.14, [1] = "Hello world" },
|
||||
functions = {
|
||||
[0] = {
|
||||
{ "pushi", 2 },
|
||||
{ "pushi", 3 },
|
||||
{ "sum" },
|
||||
{ "ret" },
|
||||
},
|
||||
[1] = {
|
||||
{ "pushi", 5000 },
|
||||
{ "ret" },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local found = assemble(source)
|
||||
-- tprint(expected)
|
||||
tprint(found)
|
||||
assert_eq(found, expected)
|
||||
end
|
||||
|
||||
print('End.')
|
||||
62
lua-temp/tyche-as.lua
Normal file
62
lua-temp/tyche-as.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
----------------------
|
||||
-- --
|
||||
-- PARSER --
|
||||
-- --
|
||||
----------------------
|
||||
|
||||
local function assemble(source)
|
||||
local proto = {
|
||||
constants = {},
|
||||
functions = {},
|
||||
}
|
||||
|
||||
local section = ''
|
||||
local current_f_id = 0
|
||||
|
||||
for line in source:gmatch("([^\n]+)") do
|
||||
local line = line:gsub("%s*;.*$", "") -- remove comments
|
||||
line = line:match("^%s*(.-)%s*$") -- trim
|
||||
|
||||
if #line == 1 then goto continue end
|
||||
|
||||
if line == ".const" then
|
||||
section = 'const'
|
||||
elseif line:match("%.func%s+%d+") then
|
||||
section = 'function'
|
||||
local f_id = tonumber(line:match("%.func%s+(%d+)"))
|
||||
proto.functions[f_id] = {}
|
||||
current_f_id = f_id
|
||||
elseif section == 'const' then
|
||||
local k, v = line:match("^%s*(%d+)%s*:%s*(.+)$")
|
||||
if v:sub(1, 1) == '"' then
|
||||
proto.constants[tonumber(k)] = line:match('"(.*)"')
|
||||
else
|
||||
proto.constants[tonumber(k)] = tonumber(v)
|
||||
end
|
||||
elseif section == 'function' then
|
||||
local inst, par = line:match("^%s*(%a+)%s+(%d+)%s*$")
|
||||
if inst then
|
||||
table.insert(proto.functions[current_f_id], { inst, tonumber(par) })
|
||||
else
|
||||
local inst = line:match("^%s*(%a+)%s*$")
|
||||
table.insert(proto.functions[current_f_id], { inst })
|
||||
end
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
return proto
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- --
|
||||
-- MAIN --
|
||||
-- --
|
||||
----------------------
|
||||
|
||||
if ... then
|
||||
return assemble
|
||||
else
|
||||
error("Running assembler directly not supported yet")
|
||||
end
|
||||
0
lua-temp/tyche-vm.lua
Normal file
0
lua-temp/tyche-vm.lua
Normal file
Reference in New Issue
Block a user