diff options
| author | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-05-28 15:00:35 +0200 |
|---|---|---|
| committer | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-05-28 15:00:35 +0200 |
| commit | a0c85883fb541f4b4daab0cf30b4ed2fa7e23262 (patch) | |
| tree | b3979ca5832cc2d282b549a784d97df83a60b4c7 /mkconvert.lua | |
| download | hydra-dragonfire-a0c85883fb541f4b4daab0cf30b4ed2fa7e23262.tar.xz | |
Initial commit
Diffstat (limited to 'mkconvert.lua')
| -rwxr-xr-x | mkconvert.lua | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/mkconvert.lua b/mkconvert.lua new file mode 100755 index 0000000..d49d46d --- /dev/null +++ b/mkconvert.lua @@ -0,0 +1,201 @@ +#!/usr/bin/env lua +local function parse_pair(pair, value_first) + if pair:sub(1, 1) == "#" then + return + end + + local idx = pair:find(" ") + + if idx then + local first, second = pair:sub(1, idx - 1), pair:sub(idx + 1) + + if value_first and first:sub(1, 1) ~= "[" then + return second, first + else + return first, second + end + else + return pair + end +end + +local function parse_spec(name, value_first) + local f = io.open("spec/" .. name, "r") + local spec = {} + local top + + for l in f:lines() do + if l:sub(1, 1) == "\t" then + local key, val = parse_pair(l:sub(2), value_first) + + if val then + top[key] = val + elseif key then + table.insert(top, key) + end + else + local key, val = parse_pair(l, value_first) + + if val then + spec[key] = val + elseif key then + top = {} + spec[key] = top + end + end + end + + f:close() + return spec +end + +local casemap = parse_spec("casemap") + +local function camel_case(snake) + if casemap[snake] then + return casemap[snake] + end + + local camel = "" + + while #snake > 0 do + local idx = snake:find("_") or #snake + 1 + + camel = camel + .. snake:sub(1, 1):upper() + .. snake:sub(2, idx - 1) + + snake = snake:sub(idx + 1) + end + + return camel +end + +local funcs = "" + +for name, fields in pairs(parse_spec("client/enum")) do + local camel = camel_case(name) + funcs = funcs .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tswitch val {\n" + + for _, var in ipairs(fields) do + funcs = funcs .. "\tcase mt." + .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") + .. ":\n\t\t" .. (var == "no" and "l.PushNil()" or "l.PushString(\"" .. var .. "\")") .. "\n" + end + + funcs = funcs .. "\t}\n}\n\n" +end + +for name, fields in pairs(parse_spec("client/flag")) do + local camel = camel_case(name) + funcs = funcs .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tl.NewTable()\n" + + for _, var in ipairs(fields) do + funcs = funcs .. "\tif val&mt." + .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") + .. " != 0 {\n\t\tl.PushBoolean(true)\n\t\tl.SetField(-2, \"" .. var .. "\")\n\t}\n" + end + + funcs = funcs .. "}\n\n" +end + +local push_type = { + string = "l.PushString(string(VAL))", + fixed_string = "l.PushString(string(VAL[:]))", + boolean = "l.PushBoolean(bool(VAL))", + integer = "l.PushInteger(int(VAL))", + number = "l.PushNumber(float64(VAL))", + vec2 = "luaPushVec2(l, [2]float64{float64(VAL[0]), float64(VAL[1])})", + vec3 = "luaPushVec3(l, [3]float64{float64(VAL[0]), float64(VAL[1]), float64(VAL[2])})", + box1 = "luaPushBox1(l, [2]float64{float64(VAL[0]), float64(VAL[1])})", + box2 = "luaPushBox2(l, [2][2]float64{{float64(VAL[0][0]), float64(VAL[0][1])}, {float64(VAL[1][0]), float64(VAL[1][1])}})", + box3 = "luaPushBox3(l, [2][3]float64{{float64(VAL[0][0]), float64(VAL[0][1]), float64(VAL[0][2])}, {float64(VAL[1][0]), float64(VAL[1][1]), float64(VAL[1][2])}})", +} + +local function push_fields(fields, indent) + local impl = "" + + for name, type in pairs(fields) do + if name:sub(1, 1) ~= "[" then + local camel = "val." .. camel_case(name) + + local idt = indent + local condition = fields["[" .. name .. "]"] + + if condition then + impl = impl .. indent .. "if " .. condition .. " {\n" + idt = idt .. "\t" + end + + if push_type[type] then + impl = impl .. idt .. push_type[type]:gsub("VAL", camel) .. "\n" + else + impl = impl .. idt .. "luaPush" .. camel_case(type) .. "(l, " .. camel .. ")\n" + end + + impl = impl .. idt .. "l.SetField(-2, \"" .. name .. "\")\n" + + if condition then + impl = impl .. indent .. "}\n" + end + end + end + + return impl +end + +for name, fields in pairs(parse_spec("client/struct", true)) do + local camel = camel_case(name) + funcs = funcs + .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tl.NewTable()\n" + .. push_fields(fields, "\t") + .. "}\n\n" +end + +local to_string_impl = "" +local to_lua_impl = "" + +for name, fields in pairs(parse_spec("client/pkt", true)) do + local case = "\tcase *mt.ToClt" .. camel_case(name) .. ":\n" + + to_string_impl = to_string_impl + .. case .. "\t\treturn \"" .. name .. "\"\n" + + if next(fields) then + to_lua_impl = to_lua_impl .. case .. push_fields(fields, "\t\t") + end +end + +local f = io.open("convert.go", "w") +f:write([[ +// generated by mkconvert.lua, DO NOT EDIT +package main + +import ( + "github.com/Shopify/go-lua" + "github.com/anon55555/mt" +) + +]] .. funcs .. [[ +func pktToString(pkt *mt.Pkt) string { + switch pkt.Cmd.(type) { +]] .. to_string_impl .. [[ + } + panic("impossible") + return "" +} + +func pktToLua(l *lua.State, pkt *mt.Pkt) { + if pkt == nil { + l.PushNil() + return + } + l.NewTable() + l.PushString(pktToString(pkt)) + l.SetField(-2, "_type") + switch val := pkt.Cmd.(type) { +]] .. to_lua_impl .. [[ + } +} +]]) +f:close() |
