]> git.lizzy.rs Git - hydra-dragonfire.git/blob - convert/read_mkauto.lua
Add map component
[hydra-dragonfire.git] / convert / read_mkauto.lua
1 #!/usr/bin/env lua
2 require("spec")
3
4 local readers = {
5         SliceByte = true,
6         Byte = true,
7         String = true,
8         SliceField = true,
9         Field = true,
10         Bool = true,
11         PointedThing = true,
12 }
13
14 local external = {
15         "[3]int16",
16         "AOID"
17 }
18
19 local function generate(name)
20         local fnname, index, child, childfn, childtype
21         local type = name
22
23         local open = name:find("%[")
24         local clos = name:find("%]")
25
26         if open == 1 then
27                 index = name:sub(open + 1, clos - 1)
28                 child = name:sub(clos + 1)
29                 childfn, childtype = generate(child)
30                 fnname = (index == "" and "Slice" or "Vec" .. index) .. childfn
31
32                 type = "[" .. index .. "]" .. childtype
33         else
34                 fnname = camel_case(name)
35
36                 local c = name:sub(1, 1)
37                 if c == c:upper() then
38                          type = "mt." .. name
39                 end
40         end
41
42         if not readers[fnname] then
43                 local fun = "func Read" .. fnname .. "(l *lua.LState, val lua.LValue, ptr *" .. type  .. ") {\n"
44
45                 if child then
46                         fun = fun .. "\tif val.Type() != lua.LTTable {\n\t\tpanic(\"invalid value for "
47                                 .. name .. ": must be a table\")\n\t}\n"
48
49                         if index == "" then
50                                 fun = fun ..
51 [[
52         tbl := val.(*lua.LTable)
53         n := tbl.MaxN()
54         *ptr = make(]] .. type .. [[, n)
55         for i := range *ptr {
56                 Read]] .. childfn .. [[(l, l.RawGetInt(tbl, i+1), &(*ptr)[i])
57         }
58 ]]
59                         else
60                                 local n = tonumber(index)
61                                 for i, v in ipairs({"x", "y", "z"}) do
62                                         if i > n then
63                                                 break
64                                         end
65
66                                         fun = fun
67                                                 .. "\tRead" .. childfn
68                                                 .. "(l, l.GetField(val, \"" .. v .. "\"), &(*ptr)[" .. (i - 1) .. "])\n"
69                                 end
70                         end
71                 else
72                         local is_float = type == "float32" or type == "float64"
73
74                         fun = fun .. "\tif val.Type() != lua.LTNumber {\n\t\tpanic(\"invalid value for "
75                                 .. name .. ": must be a number\")\n\t}\n"
76                                 .. "\t*ptr = " .. type .. "("
77                                 .. (is_float and "" or "math.Round(float64(")
78                                 .. "val.(lua.LNumber)"
79                                 .. (is_float and "" or "))")
80                                 .. ")\n"
81                 end
82
83                 fun = fun .. "}\n\n"
84
85                 readers[fnname] = fun
86         end
87
88         return fnname, type
89 end
90
91 for _, use in ipairs(external) do
92         generate(use)
93 end
94
95 local function signature(name, prefix, type)
96         local camel = camel_case(name)
97         return "func Read" .. camel .. "(l *lua.LState, val lua.LValue, ptr *" .. prefix .. camel  .. ") {\n"
98 end
99
100 for name, fields in spairs(parse_spec("server/enum")) do
101         local camel = camel_case(name)
102         local fun = signature(name, "mt.")
103
104         local impl = ""
105         for _, var in ipairs(fields) do
106                 local equals = "*ptr = mt." .. apply_prefix(fields, var) .. "\n"
107
108                 if var == "no" then
109                         fun = fun .. "\tif val.Type() == lua.LTNil {\n\t\t" .. equals .. "\t\treturn\n\t}\n"
110                 else
111                         impl = impl .. "\tcase \"" .. var .. "\":\n\t\t" .. equals
112                 end
113         end
114
115         fun = fun
116                 .. "\tif val.Type() != lua.LTString {\n\t\tpanic(\"invalid value for "
117                 .. camel .. ": must be a string\")\n\t}\n"
118                 .. "\tstr := string(val.(lua.LString))\n"
119                 .. "\tswitch str {\n" .. impl
120                 .. "\tdefault:\n\t\tpanic(\"invalid value for " .. name .. ": \" + str)\n\t}\n}\n\n"
121
122         readers[camel] = fun
123 end
124
125 for name, fields in spairs(parse_spec("server/flag")) do
126         local camel = camel_case(name)
127         local fun = signature(name, "mt.")
128                 .. "\tif val.Type() != lua.LTTable {\n\t\tpanic(\"invalid value for "
129                 .. camel .. ": must be a table\")\n\t}\n"
130
131         for _, var in ipairs(fields) do
132                 fun = fun .. "\tif l.GetField(val, \"" .. var .. "\") == lua.LTrue {\n"
133                         .. "\t\t*ptr = *ptr | mt." .. apply_prefix(fields, var) .. "\n\t}\n"
134         end
135
136         fun = fun .. "}\n\n"
137         readers[camel] = fun
138 end
139
140 local function fields_fromlua(fields, indent)
141         local impl = ""
142
143         for name, type in spairs(fields) do
144                 impl = impl .. indent .. "Read" .. generate(type) .. "(l, l.GetField(val, \"" .. name .. "\"), &ptr."
145                         .. camel_case(name) .. ")\n"
146         end
147
148         return impl
149 end
150
151 for name, fields in spairs(parse_spec("server/struct", true)) do
152         local camel = camel_case(name)
153         readers[camel] = signature(name, "mt.")
154                 .. "\tif val.Type() != lua.LTTable {\n"
155                 .. "\t\tpanic(\"invalid value for " .. camel .. ": must be a table\")\n\t}\n"
156                 .. fields_fromlua(fields, "\t")
157                 .. "}\n\n"
158 end
159
160 local pkt_impl = ""
161
162 for name, fields in spairs(parse_spec("server/pkt", true)) do
163         pkt_impl = pkt_impl
164                 .. "\tcase \"" .. name .. "\"" .. "" .. ":\n"
165                 .. "\t\tptr := &mt.ToSrv" .. camel_case(name) .. "{}\n"
166
167         if next(fields) then
168                 pkt_impl = pkt_impl
169                         .. "\t\tval := l.CheckTable(3)\n"
170                         .. fields_fromlua(fields, "\t\t")
171         end
172
173         pkt_impl = pkt_impl
174                 .. "\t\treturn ptr\n"
175 end
176
177 local funcs = ""
178 for _, fn in spairs(readers) do
179         if type(fn) == "string" then
180                 funcs = funcs .. fn
181         end
182 end
183
184 local f = io.open("read_auto.go", "w")
185 f:write([[
186 // generated by read_mkauto.lua, DO NOT EDIT
187 package convert
188
189 import (
190         "github.com/anon55555/mt"
191         "github.com/yuin/gopher-lua"
192         "math"
193 )
194
195 ]] .. funcs .. [[
196 func ReadCmd(l *lua.LState) mt.Cmd {
197         str := l.CheckString(2)
198         switch str {
199 ]] .. pkt_impl .. [[
200         }
201
202         panic("invalid packet type: " + str)
203 }
204 ]])
205 f:close()