This commit is contained in:
Andre Wagner
2026-05-04 11:24:35 -05:00
parent 9bc6ad1c92
commit 8a685ebbc8
6 changed files with 279 additions and 0 deletions

35
lua-temp/doc/BYTECODE Normal file
View 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
View 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
View 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
View 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
View 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
View File