diff svk/generate.nim @ 1489:e6bd1f553c1b default tip main

add: quite a bit more wrapper
author sam <sam@basx.dev>
date Sun, 18 May 2025 23:47:16 +0700
parents 3ce7c132fdac
children
line wrap: on
line diff
--- a/svk/generate.nim	Sun May 18 16:36:52 2025 +0700
+++ b/svk/generate.nim	Sun May 18 23:47:16 2025 +0700
@@ -55,6 +55,7 @@
     name: string
     values: seq[EnumEntry]
     isBitmask: bool
+    nBytes: int = 4
 
   ConstantDef = object
     name: string
@@ -203,7 +204,8 @@
       edef.addValue(ee)
     enums[edef.name] = edef
   elif e.attr("type") == "bitmask":
-    var edef = EnumDef(name: e.attr("name"), isBitmask: true)
+    let nBytes = if e.attr("bitwidth") == "": 4 else: parseInt(e.attr("bitwidth")) div 8
+    var edef = EnumDef(name: e.attr("name"), isBitmask: true, nBytes: nBytes)
     for ee in e.findAll("enum"):
       edef.addValue(ee)
     enums[edef.name] = edef
@@ -236,8 +238,6 @@
 outFile.writeLine """
 
 import std/dynlib
-import std/strutils
-import std/tables
 import std/macros
 import std/typetraits
 
@@ -255,16 +255,6 @@
 macro enumFullRange(a: typed): untyped =
   newNimNode(nnkBracket).add(a.getType[1][1 ..^ 1])
 
-func asBits[T, S](flags: openArray[T]): S =
-  for flag in flags:
-    let a = distinctBase(S)(result)
-    let b = distinctBase(S)(flag)
-    result = S(a or b)
-
-func toEnums*[T, S](number: T): seq[S] =
-  for value in enumFullRange(S):
-    if (value.ord and cint(number)) > 0:
-      result.add value
 """
 
 outFile.writeLine "type"
@@ -352,7 +342,7 @@
 
 for edef in enums.values():
   if edef.values.len > 0:
-    outFile.writeLine &"type {edef.name}* {{.size: 4.}} = enum"
+    outFile.writeLine &"type {edef.name}* {{.size: {edef.nBytes}.}} = enum"
     for ee in edef.values:
       # due to the nim identifier-system, there might be collisions between typenames and enum-member names
       if ee.name in nameCollisions:
@@ -432,14 +422,25 @@
 for edef in enums.values():
   if edef.values.len > 0:
     if edef.isBitmask:
-      let bitsName = edef.name
-      let p = bitsName.rfind("FlagBits")
-      let flagsName = bitsName[0 ..< p] & "Flags" & bitsName[p + 8 .. ^1]
+      let enumName = edef.name
+      let p = enumName.rfind("FlagBits")
+      let flagSetType = enumName[0 ..< p] & "Flags" & enumName[p + 8 .. ^1]
 
-      outFile.writeLine &"converter {bitsName}ToBits*(flags: openArray[{bitsName}]): {flagsName} ="
-      outFile.writeLine &"  asBits[{bitsName}, {flagsName}](flags)"
-      outFile.writeLine &"func `$`*(bits: {flagsName}): string ="
-      outFile.writeLine &"  $toEnums[{flagsName}, {bitsName}](bits)"
+      outFile.writeLine &"""
+func `or`(a: {flagSetType}, b: {enumName}): {flagSetType} {{.hint[XDeclaredButNotUsed]: off.}} =
+  {flagSetType}(distinctBase({flagSetType})(a) or distinctBase({flagSetType})(b))
+func `or`(a, b: {enumName}): {flagSetType} {{.hint[XDeclaredButNotUsed]: off.}} =
+  {flagSetType}(distinctBase({flagSetType})(a) or distinctBase({flagSetType})(b))
+func contains(flags: {flagSetType}, flag: {enumName}): bool {{.hint[XDeclaredButNotUsed]: off.}} =
+  (distinctBase({flagSetType})(flags) and distinctBase({flagSetType})(flag)) > 0
+"""
+      outFile.writeLine &"func `$`*(bits: {flagSetType}): string ="
+      outFile.writeLine &"""
+  for value in enumFullRange({enumName}):
+    if (value.ord and cint(bits)) > 0:
+      result &= $value & "|"
+  result.setLen(max(0, result.len - 1))
+"""
 outFile.writeLine ""
 
 for command in commands: