]> git.lizzy.rs Git - hydra-dragonfire.git/blob - convert/read_mkauto.lua
f749f9920cc0210d932e167e196d69cefc0f0229
[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 static_uses = {
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                         fun = fun .. "\tif val.Type() != lua.LTNumber {\n\t\tpanic(\"invalid value for "
73                                 .. name .. ": must be a number\")\n\t}\n"
74                                 .. "\t*ptr = " .. type .. "(val.(lua.LNumber))\n"
75                 end
76
77                 fun = fun .. "}\n\n"
78
79                 readers[fnname] = fun
80         end
81
82         return fnname, type
83 end
84
85 for _, use in ipairs(static_uses) do
86         generate(use)
87 end
88
89 local function signature(name, prefix, type)
90         local camel = camel_case(name)
91         return "func read" .. camel .. "(l *lua.LState, val lua.LValue, ptr *" .. prefix .. camel  .. ") {\n"
92 end
93
94 for name, fields in spairs(parse_spec("server/enum")) do
95         local camel = camel_case(name)
96         local fun = signature(name, "mt.")
97
98         local impl = ""
99         for _, var in ipairs(fields) do
100                 local equals = "*ptr = mt." .. apply_prefix(fields, var) .. "\n"
101
102                 if var == "no" then
103                         fun = fun .. "\tif val.Type() == lua.LTNil {\n\t\t" .. equals .. "\t\treturn\n\t}\n"
104                 else
105                         impl = impl .. "\tcase \"" .. var .. "\":\n\t\t" .. equals
106                 end
107         end
108
109         fun = fun
110                 .. "\tif val.Type() != lua.LTString {\n\t\tpanic(\"invalid value for "
111                 .. camel .. ": must be a string\")\n\t}\n"
112                 .. "\tstr := string(val.(lua.LString))\n"
113                 .. "\tswitch str {\n" .. impl
114                 .. "\tdefault:\n\t\tpanic(\"invalid value for " .. name .. ": \" + str)\n\t}\n}\n\n"
115
116         readers[camel] = fun
117 end
118
119 for name, fields in spairs(parse_spec("server/flag")) do
120         local camel = camel_case(name)
121         local fun = signature(name, "mt.")
122                 .. "\tif val.Type() != lua.LTTable {\n\t\tpanic(\"invalid value for "
123                 .. camel .. ": must be a table\")\n\t}\n"
124
125         for _, var in ipairs(fields) do
126                 fun = fun .. "\tif l.GetField(val, \"" .. var .. "\") == lua.LTrue {\n"
127                         .. "\t\t*ptr = *ptr | mt." .. apply_prefix(fields, var) .. "\n\t}\n"
128         end
129
130         fun = fun .. "}\n\n"
131         readers[camel] = fun
132 end
133
134 local function fields_fromlua(fields, indent)
135         local impl = ""
136
137         for name, type in spairs(fields) do
138                 impl = impl .. indent .. "read" .. generate(type) .. "(l, l.GetField(val, \"" .. name .. "\"), &ptr."
139                         .. camel_case(name) .. ")\n"
140         end
141
142         return impl
143 end
144
145 for name, fields in spairs(parse_spec("server/struct", true)) do
146         local camel = camel_case(name)
147         readers[camel] = signature(name, "mt.")
148                 .. "\tif val.Type() != lua.LTTable {\n"
149                 .. "\t\tpanic(\"invalid value for " .. camel .. ": must be a table\")\n\t}\n"
150                 .. fields_fromlua(fields, "\t")
151                 .. "}\n\n"
152 end
153
154 local pkt_impl = ""
155
156 for name, fields in spairs(parse_spec("server/pkt", true)) do
157         pkt_impl = pkt_impl
158                 .. "\tcase \"" .. name .. "\"" .. "" .. ":\n"
159                 .. "\t\tptr := &mt.ToSrv" .. camel_case(name) .. "{}\n"
160
161         if next(fields) then
162                 pkt_impl = pkt_impl
163                         .. "\t\tval := l.CheckTable(3)\n"
164                         .. fields_fromlua(fields, "\t\t")
165         end
166
167         pkt_impl = pkt_impl
168                 .. "\t\treturn ptr\n"
169 end
170
171 local funcs = ""
172 for _, fn in spairs(readers) do
173         if type(fn) == "string" then
174                 funcs = funcs .. fn
175         end
176 end
177
178 local f = io.open("read_auto.go", "w")
179 f:write([[
180 // generated by read_mkauto.lua, DO NOT EDIT
181 package convert
182
183 import (
184         "github.com/anon55555/mt"
185         "github.com/yuin/gopher-lua"
186 )
187
188 ]] .. funcs .. [[
189 func ReadCmd(l *lua.LState) mt.Cmd {
190         str := l.CheckString(2)
191         switch str {
192 ]] .. pkt_impl .. [[
193         }
194
195         panic("invalid packet type: " + str)
196 }
197 ]])
198 f:close()