Mercurial > games > semicongine
comparison svk/generate.nim @ 1480:0b302531f5c5
did: continue on vulkan nim api generator
| author | sam <sam@basx.dev> |
|---|---|
| date | Mon, 21 Apr 2025 01:31:55 +0700 |
| parents | 172ac338f820 |
| children | a99f3227130c |
comparison
equal
deleted
inserted
replaced
| 1479:172ac338f820 | 1480:0b302531f5c5 |
|---|---|
| 1 import std/strtabs | 1 import std/strtabs |
| 2 import std/syncio | |
| 2 import std/xmltree | 3 import std/xmltree |
| 3 import std/tables | 4 import std/tables |
| 4 import std/options | 5 import std/options |
| 5 import std/sequtils | 6 import std/sequtils |
| 6 import std/strutils | 7 import std/strutils |
| 7 import std/strformat | 8 import std/strformat |
| 8 import std/xmlparser | 9 import std/xmlparser |
| 9 import std/os | 10 import std/os |
| 11 import std/osproc | |
| 10 import std/paths | 12 import std/paths |
| 11 | 13 |
| 12 # helpers | 14 # helpers |
| 13 func smartParseInt(value: string): int = | 15 func smartParseInt(value: string): int = |
| 14 if value.startsWith("0x"): | 16 if value.startsWith("0x"): |
| 91 v = -v | 93 v = -v |
| 92 value = $(v) | 94 value = $(v) |
| 93 | 95 |
| 94 edef.values.add EnumEntry(name: n.attr("name"), value: value) | 96 edef.values.add EnumEntry(name: n.attr("name"), value: value) |
| 95 | 97 |
| 98 func memberDecl(n: XmlNode): string = | |
| 99 for i in 0 ..< n.len: | |
| 100 if n[i].kind == xnElement and n[i].tag == "comment": | |
| 101 n.delete(i) | |
| 102 break | |
| 103 assert n.tag == "member" | |
| 104 debugecho n.toSeq, " ", n.len | |
| 105 if n.len == 2: | |
| 106 return &"{n[1][0].text}: {n[0][0]}" | |
| 107 elif n.len == 3: | |
| 108 if n[1].kind == xnElement and n[1].tag == "name": | |
| 109 return | |
| 110 &"{n[1][0].text}: array[{n[2].text[1 ..< ^1]}, {TYPEMAP.getOrDefault(n[0][0].text, n[0][0].text)}]]" | |
| 111 else: | |
| 112 assert n[1].text.strip() == "*" | |
| 113 return &"{n[2][0].text}: ptr {n[0][0].text}" | |
| 114 elif n.len == 4: | |
| 115 if n[0].text.strip() in ["struct", "const struct"]: | |
| 116 return &"{n[3][0].text}: ptr {n[1][0].text}" | |
| 117 else: | |
| 118 assert n[2].text.strip() in ["*", "* const *", "* const*"] | |
| 119 return &"?" | |
| 120 elif n.len in [5, 6]: | |
| 121 return &"{n[1][0].text}: array[{n[3][0].text}, {n[0][0].text}]" | |
| 122 assert false | |
| 123 | |
| 96 for e in xmlenums: | 124 for e in xmlenums: |
| 97 if e.attr("type") == "constants": | 125 if e.attr("type") == "constants": |
| 98 for c in e.findAll("enum"): | 126 for c in e.findAll("enum"): |
| 99 var value = c.attr("value").strip(chars = {'(', ')'}) | 127 var value = c.attr("value").strip(chars = {'(', ')'}) |
| 100 consts.add ConstantDef( | 128 consts.add ConstantDef( |
| 122 if extendenum.attr("extends") != "": | 150 if extendenum.attr("extends") != "": |
| 123 if extendenum.attr("extnumber") == "": | 151 if extendenum.attr("extnumber") == "": |
| 124 extendenum.attrs["extnumber"] = extNum | 152 extendenum.attrs["extnumber"] = extNum |
| 125 enums[extendenum.attr("extends")].addValue(extendenum) | 153 enums[extendenum.attr("extends")].addValue(extendenum) |
| 126 | 154 |
| 155 let outPath = (system.currentSourcePath.parentDir() / "api.nim") | |
| 156 let outFile = open(outPath, fmWrite) | |
| 157 | |
| 127 # generate core types =============================================================================== | 158 # generate core types =============================================================================== |
| 128 # preamble, much easier to hardcode than to generate from xml | 159 # preamble, much easier to hardcode than to generate from xml |
| 129 echo """ | 160 outFile.writeLine """ |
| 130 when defined(linux): | |
| 131 include ./platform/xlib | |
| 132 when defined(windows): | |
| 133 include ./platform/win32 | |
| 134 | |
| 135 func VK_MAKE_API_VERSION*( | 161 func VK_MAKE_API_VERSION*( |
| 136 variant: uint32, major: uint32, minor: uint32, patch: uint32 | 162 variant: uint32, major: uint32, minor: uint32, patch: uint32 |
| 137 ): uint32 {.compileTime.} = | 163 ): uint32 {.compileTime.} = |
| 138 (variant shl 29) or (major shl 22) or (minor shl 12) or patch | 164 (variant shl 29) or (major shl 22) or (minor shl 12) or patch |
| 139 | |
| 140 | |
| 141 """ | 165 """ |
| 142 | 166 |
| 143 echo "type" | 167 outFile.writeLine "type" |
| 168 outFile.writeLine """ | |
| 169 VkSampleMask = distinct uint32 | |
| 170 VkBool32 = distinct uint32 | |
| 171 VkFlags = distinct uint32 | |
| 172 VkFlags64 = distinct uint64 | |
| 173 VkDeviceSize = distinct uint64 | |
| 174 VkDeviceAddress = distinct uint64 | |
| 175 VkRemoteAddressNV = pointer | |
| 176 """ | |
| 144 | 177 |
| 145 for t in types: | 178 for t in types: |
| 179 if t.attr("api") == "vulkansc": | |
| 180 continue | |
| 181 if t.attr("alias") != "": | |
| 182 continue | |
| 146 if t.attr("deprecated") == "true": | 183 if t.attr("deprecated") == "true": |
| 147 continue | 184 continue |
| 148 echo t | 185 if t.attr("category") == "include": |
| 149 echo "" | 186 continue |
| 187 if t.attr("category") == "define": | |
| 188 continue | |
| 189 if t.attr("category") == "bitmask": | |
| 190 if t.len > 0 and t[0].text.startsWith("typedef"): | |
| 191 outFile.writeLine &" {t[2][0].text} = distinct {t[1][0].text}" | |
| 192 elif t.attr("category") == "union": | |
| 193 let n = t.attr("name") | |
| 194 outFile.writeLine &" {n}* {{.union.}} = object" | |
| 195 for member in t.findAll("member"): | |
| 196 outFile.writeLine &" {member.memberDecl()}" | |
| 197 elif t.attr("category") == "handle": | |
| 198 outFile.writeLine &" {t[2][0].text} = distinct pointer" | |
| 199 elif t.attr("category") == "struct": | |
| 200 let n = t.attr("name") | |
| 201 outFile.writeLine &" {n}* = object" | |
| 202 for member in t.findAll("member"): | |
| 203 outFile.writeLine &" {member.memberDecl()}" | |
| 204 # TODO: funcpointer | |
| 205 | |
| 206 outFile.writeLine "" | |
| 150 | 207 |
| 151 # generate consts =============================================================================== | 208 # generate consts =============================================================================== |
| 152 echo "const" | 209 outFile.writeLine "const" |
| 153 for c in consts: | 210 for c in consts: |
| 154 var value = c.value | 211 var value = c.value |
| 155 if value.endsWith("U"): | 212 if value.endsWith("U"): |
| 156 value = value[0 ..^ 2] & "'u32" | 213 value = value[0 ..^ 2] & "'u32" |
| 157 elif value.endsWith("ULL"): | 214 elif value.endsWith("ULL"): |
| 158 value = value[0 ..^ 4] & "'u64" | 215 value = value[0 ..^ 4] & "'u64" |
| 159 if value[0] == '~': | 216 if value[0] == '~': |
| 160 value = "not " & value[1 ..^ 1] | 217 value = "not " & value[1 ..^ 1] |
| 161 echo &" {c.name}*: {c.datatype} = {value}" | 218 outFile.writeLine &" {c.name}*: {c.datatype} = {value}" |
| 162 echo "" | 219 outFile.writeLine "" |
| 163 | 220 |
| 164 # generate enums =============================================================================== | 221 # generate enums =============================================================================== |
| 165 echo "type" | 222 outFile.writeLine "type" |
| 166 for edef in enums.values(): | 223 for edef in enums.values(): |
| 167 if edef.values.len > 0: | 224 if edef.values.len > 0: |
| 168 echo &" {edef.name}* {{.size: 4.}} = enum" | 225 outFile.writeLine &" {edef.name}* {{.size: 4.}} = enum" |
| 169 for ee in edef.values: | 226 for ee in edef.values: |
| 170 echo &" {ee.name} = {ee.value}" | 227 outFile.writeLine &" {ee.name} = {ee.value}" |
| 171 echo "" | 228 outFile.writeLine "" |
| 229 | |
| 230 outFile.writeLine """ | |
| 231 when defined(linux): | |
| 232 include ../semicongine/rendering/vulkan/platform/xlib | |
| 233 when defined(windows): | |
| 234 include ../semicongine/rendering/vulkan/platform/win32 | |
| 235 """ | |
| 236 | |
| 237 outFile.close() | |
| 238 | |
| 239 assert execCmd("nim c " & outPath) == 0 |
