aboutsummaryrefslogtreecommitdiff
path: root/bindgen/gen_nim.py
diff options
context:
space:
mode:
authorGustav Olsson <gustav.olsson@hey.com>2022-05-18 00:39:24 +0200
committerGustav Olsson <gustav.olsson@hey.com>2022-05-18 02:03:36 +0200
commitea8a628c2e5b83ba4717aae7012230a23ed1566f (patch)
tree1c831504f4be8c535b85ccb46d826f0a517699b6 /bindgen/gen_nim.py
parent173da5b453a54721fa5a9b312b99de656e885c45 (diff)
update nim bindgen
* follow nim code style * avoid keyword clashes * remove redundant functions * use nim bitfields for some consts * generate bindings for sokol_glue.h
Diffstat (limited to 'bindgen/gen_nim.py')
-rw-r--r--bindgen/gen_nim.py420
1 files changed, 188 insertions, 232 deletions
diff --git a/bindgen/gen_nim.py b/bindgen/gen_nim.py
index fb6ba450..df8758ee 100644
--- a/bindgen/gen_nim.py
+++ b/bindgen/gen_nim.py
@@ -2,8 +2,8 @@
# Read output of gen_json.py and generate Zig language bindings.
#
# Nim coding style:
-# - types and constants are PascalCase
-# - functions, parameters, and fields are camelCase
+# - type identifiers are PascalCase, everything else is camelCase
+# - reference: https://nim-lang.org/docs/nep1.html
#-------------------------------------------------------------------------------
import gen_ir
import json, re, os, shutil
@@ -11,6 +11,7 @@ import json, re, os, shutil
module_names = {
'sg_': 'gfx',
'sapp_': 'app',
+ 'sapp_sg': 'glue',
'stm_': 'time',
'saudio_': 'audio',
'sgl_': 'gl',
@@ -19,13 +20,14 @@ module_names = {
}
c_source_paths = {
- 'sg_': 'sokol-nim/src/sokol/c/sokol_gfx.c',
- 'sapp_': 'sokol-nim/src/sokol/c/sokol_app.c',
- 'stm_': 'sokol-nim/src/sokol/c/sokol_time.c',
- 'saudio_': 'sokol-nim/src/sokol/c/sokol_audio.c',
- 'sgl_': 'sokol-nim/src/sokol/c/sokol_gl.c',
- 'sdtx_': 'sokol-nim/src/sokol/c/sokol_debugtext.c',
- 'sshape_': 'sokol-nim/src/sokol/c/sokol_shape.c',
+ 'sg_': 'sokol-nim/src/sokol/gen/sokol_gfx.c',
+ 'sapp_': 'sokol-nim/src/sokol/gen/sokol_app.c',
+ 'sapp_sg': 'sokol-nim/src/sokol/gen/sokol_glue.c',
+ 'stm_': 'sokol-nim/src/sokol/gen/sokol_time.c',
+ 'saudio_': 'sokol-nim/src/sokol/gen/sokol_audio.c',
+ 'sgl_': 'sokol-nim/src/sokol/gen/sokol_gl.c',
+ 'sdtx_': 'sokol-nim/src/sokol/gen/sokol_debugtext.c',
+ 'sshape_': 'sokol-nim/src/sokol/gen/sokol_shape.c',
}
func_name_ignores = [
@@ -39,15 +41,29 @@ func_name_overrides = {
'sgl_rad': 'sgl_as_radians',
}
+# consts that should be converted to Nim enum bitfields, values mimic C type declarations
+const_bitfield_overrides = {
+ 'SAPP_MODIFIER_': 'sapp_event_modifier',
+}
+
struct_field_type_overrides = {
- 'sg_context_desc.color_format': 'int',
- 'sg_context_desc.depth_format': 'int',
+ 'sapp_event.modifiers': 'sapp_event_modifiers', # note the extra 's' at the end
+ 'sapp_allocator.alloc': 'void * (*)(size_t, void *)',
+ 'sapp_allocator.free': 'void (*)(void *, void *)',
+ 'sg_allocator.alloc': 'void * (*)(size_t, void *)',
+ 'sg_allocator.free': 'void (*)(void *, void *)',
+ 'sgl_allocator_t.alloc': 'void * (*)(size_t, void *)',
+ 'sgl_allocator_t.free': 'void (*)(void *, void *)',
+ 'sdtx_allocator_t.alloc': 'void * (*)(size_t, void *)',
+ 'sdtx_allocator_t.free': 'void (*)(void *, void *)',
+ 'saudio_allocator.alloc': 'void * (*)(size_t, void *)',
+ 'saudio_allocator.free': 'void (*)(void *, void *)',
}
prim_types = {
- 'int': 'int32',
+ 'int': 'cint',
'bool': 'bool',
- 'char': 'char',
+ 'char': 'cchar',
'int8_t': 'int8',
'uint8_t': 'uint8',
'int16_t': 'int16',
@@ -56,11 +72,11 @@ prim_types = {
'uint32_t': 'uint32',
'int64_t': 'int64',
'uint64_t': 'uint64',
- 'float': 'float32',
- 'double': 'float64',
+ 'float': 'cfloat',
+ 'double': 'cdouble',
'uintptr_t': 'uint',
'intptr_t': 'int',
- 'size_t': 'int',
+ 'size_t': 'csize_t',
}
prim_defaults = {
@@ -74,13 +90,49 @@ prim_defaults = {
'uint32_t': '0',
'int64_t': '0',
'uint64_t': '0',
- 'float': '0.0',
+ 'float': '0.0f',
'double': '0.0',
'uintptr_t': '0',
'intptr_t': '0',
'size_t': '0'
}
+common_prim_types = """
+untyped typed void
+bool byte char
+int int8 int16 int32 int64
+uint uint8 uint16 uint32 uint64
+float float32 float64
+string
+cchar cint csize_t
+cfloat cdouble
+cstring
+pointer
+""".split()
+
+keywords = """
+addr and as asm
+bind block break
+case cast concept const continue converter
+defer discard distinct div do
+elif else end enum except export
+finally for from func
+if import in include interface is isnot iterator
+let
+macro method mixin mod
+nil not notin
+object of or out
+proc ptr
+raise ref return
+shl shr static
+template try tuple type
+using
+var
+when while
+xor
+yield
+""".split() + common_prim_types
+
struct_types = []
enum_types = []
enum_items = {}
@@ -96,8 +148,7 @@ def reset_globals():
enum_items = {}
out_lines = ''
-re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
-re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
+re_array = re.compile("([a-z_\d\s\*]+)\s*\[(\d+)\]")
def l(s):
global out_lines
@@ -107,27 +158,12 @@ def as_nim_prim_type(s):
return prim_types[s]
# prefix_bla_blub(_t) => (dep.)BlaBlub
-def as_nim_struct_type(s, prefix):
+def as_nim_type_name(s, prefix):
parts = s.lower().split('_')
- outp = '' if s.startswith(prefix) else f'{parts[0]}.'
- for part in parts[1:]:
- if (part != 't'):
- outp += part.capitalize()
- return outp
-
-# prefix_bla_blub(_t) => (dep.)BlaBlub
-def as_nim_enum_type(s, prefix):
- parts = s.lower().split('_')
- outp = '' if s.startswith(prefix) else f'{parts[0]}.'
- for part in parts[1:]:
- if (part != 't'):
- outp += part.capitalize()
- return outp
-
-# prefix_bla_blub(_t) => (dep.)BlaBlub
-def as_nim_const_type(s, prefix):
- parts = s.lower().split('_')
- outp = '' if s.startswith(prefix) else f'{parts[0]}.'
+ dep = parts[0] + '_'
+ outp = ''
+ if not s.startswith(prefix) and dep in module_names:
+ outp = module_names[dep] + '.'
for part in parts[1:]:
if (part != 't'):
outp += part.capitalize()
@@ -149,15 +185,28 @@ def check_func_name_override(func_name):
else:
return func_name
+def is_power_of_two(val):
+ return val == 0 or val & (val - 1) == 0
+
+def check_consts_bitfield_override(decl):
+ for override in const_bitfield_overrides:
+ if all(override in item['name'] for item in decl['items']):
+ if any(not is_power_of_two(int(item['value'])) for item in decl['items']):
+ print(f"warning: bitfield override '{override}' encountered non-power-of-two value")
+ return const_bitfield_overrides[override]
+ return None
+
def trim_prefix(s, prefix):
outp = s;
if outp.lower().startswith(prefix.lower()):
outp = outp[len(prefix):]
return outp
-# PREFIX_BLA_BLUB to bla_blub
-def as_snake_case(s, prefix = ""):
- return trim_prefix(s, prefix).lower()
+def wrap_keywords(s):
+ if s in keywords:
+ return f'`{s}`'
+ else:
+ return s
# prefix_bla_blub => blaBlub
def as_camel_case(s, prefix = ""):
@@ -165,7 +214,7 @@ def as_camel_case(s, prefix = ""):
outp = parts[0]
for part in parts[1:]:
outp += part.capitalize()
- return outp
+ return wrap_keywords(outp)
# prefix_bla_blub => BlaBlub
def as_pascal_case(s, prefix):
@@ -173,20 +222,20 @@ def as_pascal_case(s, prefix):
outp = ""
for part in parts:
outp += part.capitalize()
- return outp
+ return wrap_keywords(outp)
-# PREFIX_ENUM_BLA => Bla, _PREFIX_ENUM_BLA => Bla
+# PREFIX_ENUM_BLA_BLO => Bla, _PREFIX_ENUM_BLA_BLO => blaBlo
def as_enum_item_name(s):
outp = s
if outp.startswith('_'):
outp = outp[1:]
parts = outp.lower().split('_')[2:]
- outp = ""
- for part in parts:
+ outp = parts[0]
+ for part in parts[1:]:
outp += part.capitalize()
if outp[0].isdigit():
- outp = 'N' + outp
- return outp
+ outp = 'n' + outp
+ return wrap_keywords(outp)
def enum_default_item(enum_name):
return enum_items[enum_name][0]
@@ -230,20 +279,17 @@ def is_const_struct_ptr(s):
def is_func_ptr(s):
return '(*)' in s
-def is_1d_array_type(s):
- return re_1d_array.match(s)
-
-def is_2d_array_type(s):
- return re_2d_array.match(s)
+def is_array_type(s):
+ return re_array.match(s) is not None
def type_default_value(s):
return prim_defaults[s]
def extract_array_type(s):
- return s[:s.index('[')].strip()
+ return s[:s.find('[')].strip() + s[s.find(']')+1:].strip()
def extract_array_nums(s):
- return s[s.index('['):].replace('[', ' ').replace(']', ' ').split()
+ return s[s.find('[')+1:s.find(']')].strip()
def extract_ptr_type(s):
tokens = s.split()
@@ -252,239 +298,141 @@ def extract_ptr_type(s):
else:
return tokens[0]
-def as_extern_c_arg_type(arg_type, prefix):
- if arg_type == "void":
- return "void"
- elif is_prim_type(arg_type):
- return as_nim_prim_type(arg_type)
- elif is_struct_type(arg_type):
- return as_nim_struct_type(arg_type, prefix)
- elif is_enum_type(arg_type):
- return as_nim_enum_type(arg_type, prefix)
- elif is_void_ptr(arg_type):
- return "pointer"
- elif is_const_void_ptr(arg_type):
- return "pointer"
- elif is_string_ptr(arg_type):
+def as_nim_type(ctype, prefix):
+ if ctype == "void":
+ return ""
+ elif is_prim_type(ctype):
+ return as_nim_prim_type(ctype)
+ elif is_struct_type(ctype):
+ return as_nim_type_name(ctype, prefix)
+ elif is_enum_type(ctype):
+ return as_nim_type_name(ctype, prefix)
+ elif is_string_ptr(ctype):
return "cstring"
- elif is_const_struct_ptr(arg_type):
- return f"ptr {as_nim_struct_type(extract_ptr_type(arg_type), prefix)}"
- elif is_prim_ptr(arg_type):
- return f"[*c] {as_nim_prim_type(extract_ptr_type(arg_type))}"
- elif is_const_prim_ptr(arg_type):
- return f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
- else:
- return '??? (as_extern_c_arg_type)'
-
-def as_nim_arg_type(arg_prefix, arg_type, prefix):
- # NOTE: if arg_prefix is None, the result is used as return value
- pre = "" if arg_prefix is None else arg_prefix
- if arg_type == "void":
- if arg_prefix is None:
- return "void"
- else:
- return ""
- elif is_prim_type(arg_type):
- return pre + as_nim_prim_type(arg_type)
- elif is_struct_type(arg_type):
- return pre + as_nim_struct_type(arg_type, prefix)
- elif is_enum_type(arg_type):
- return pre + as_nim_enum_type(arg_type, prefix)
- elif is_void_ptr(arg_type):
- return pre + "pointer"
- elif is_const_void_ptr(arg_type):
- return pre + "pointer"
- elif is_string_ptr(arg_type):
- return pre + "cstring"
- elif is_const_struct_ptr(arg_type):
- return pre + f"ptr {as_nim_struct_type(extract_ptr_type(arg_type), prefix)}"
- elif is_prim_ptr(arg_type):
- return pre + f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
- elif is_const_prim_ptr(arg_type):
- return pre + f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
+ elif is_void_ptr(ctype) or is_const_void_ptr(ctype):
+ return "pointer"
+ elif is_const_struct_ptr(ctype):
+ return f"ptr {as_nim_type(extract_ptr_type(ctype), prefix)}"
+ elif is_prim_ptr(ctype) or is_const_prim_ptr(ctype):
+ return f"ptr {as_nim_type(extract_ptr_type(ctype), prefix)}"
+ elif is_func_ptr(ctype):
+ args = funcptr_args(ctype, prefix)
+ res = funcptr_res(ctype, prefix)
+ if res != "":
+ res = ":" + res
+ return f"proc({args}){res} {{.cdecl.}}"
+ elif is_array_type(ctype):
+ array_ctype = extract_array_type(ctype)
+ array_nums = extract_array_nums(ctype)
+ return f"array[{array_nums}, {as_nim_type(array_ctype, prefix)}]"
else:
- return arg_prefix + "??? (as_nim_arg_type)"
+ l(f"// FIXME: {ctype};")
-# get C-style arguments of a function pointer as string
-def funcptr_args_c(field_type, prefix):
+def funcptr_args(field_type, prefix):
tokens = field_type[field_type.index('(*)')+4:-1].split(',')
s = ""
n = 0
for token in tokens:
n += 1
- arg_type = token.strip()
+ arg_ctype = token.strip()
if s != "":
s += ", "
- c_arg = f"a{n}:" + as_extern_c_arg_type(arg_type, prefix)
- if (c_arg == "void"):
- return ""
- else:
- s += c_arg
+ arg_nimtype = as_nim_type(arg_ctype, prefix)
+ if arg_nimtype == "":
+ return "" # fun(void)
+ s += f"a{n}:{arg_nimtype}"
if s == "a1:void":
s = ""
return s
-# get C-style result of a function pointer as string
-def funcptr_res_c(field_type):
- res_type = field_type[:field_type.index('(*)')].strip()
- if res_type == 'void':
- return ''
- elif is_const_void_ptr(res_type):
- return ':pointer'
- else:
- return '???'
+def funcptr_res(field_type, prefix):
+ ctype = field_type[:field_type.index('(*)')].strip()
+ return as_nim_type(ctype, prefix)
-def funcdecl_args_c(decl, prefix):
- s = ""
- for param_decl in decl['params']:
- if s != "":
- s += ", "
- arg_type = param_decl['type']
- s += as_extern_c_arg_type(arg_type, prefix)
- return s
-
-def funcdecl_args_nim(decl, prefix):
+def funcdecl_args(decl, prefix):
s = ""
for param_decl in decl['params']:
if s != "":
s += ", "
arg_name = param_decl['name']
arg_type = param_decl['type']
- s += f"{as_nim_arg_type(f'{arg_name}:', arg_type, prefix)}"
+ s += f"{arg_name}:{as_nim_type(arg_type, prefix)}"
return s
-def funcdecl_res_c(decl, prefix):
- decl_type = decl['type']
- res_type = decl_type[:decl_type.index('(')].strip()
- return as_extern_c_arg_type(res_type, prefix)
-
-def funcdecl_res_nim(decl, prefix):
+def funcdecl_res(decl, prefix):
decl_type = decl['type']
res_type = decl_type[:decl_type.index('(')].strip()
- nim_res_type = as_nim_arg_type(None, res_type, prefix)
+ nim_res_type = as_nim_type(res_type, prefix)
if nim_res_type == "":
nim_res_type = "void"
return nim_res_type
def gen_struct(decl, prefix, use_raw_name=False):
struct_name = decl['name']
- nim_type = struct_name if use_raw_name else as_nim_struct_type(struct_name, prefix)
+ nim_type = struct_name if use_raw_name else as_nim_type_name(struct_name, prefix)
l(f"type {nim_type}* = object")
- isPublic = True
+ is_public = True
for field in decl['fields']:
field_name = field['name']
if field_name == "__pad":
# FIXME: these should be guarded by SOKOL_ZIG_BINDINGS, but aren't?
continue
- isPublic = not field_name.startswith("_")
+ is_public = not field_name.startswith("_")
field_name = as_camel_case(field_name, "_")
- if field_name == "ptr":
- field_name = "source"
- if field_name == "ref":
- field_name = "`ref`"
- if field_name == "type":
- field_name = "`type`"
- if isPublic:
+ if is_public:
field_name += "*"
- field_type = field['type']
- field_type = check_struct_field_type_override(struct_name, field_name, field_type)
- if is_prim_type(field_type):
- l(f" {field_name}:{as_nim_prim_type(field_type)}")
- elif is_struct_type(field_type):
- l(f" {field_name}:{as_nim_struct_type(field_type, prefix)}")
- elif is_enum_type(field_type):
- l(f" {field_name}:{as_nim_enum_type(field_type, prefix)}")
- elif is_string_ptr(field_type):
- l(f" {field_name}:cstring")
- elif is_const_void_ptr(field_type):
- l(f" {field_name}:pointer")
- elif is_void_ptr(field_type):
- l(f" {field_name}:pointer")
- elif is_const_prim_ptr(field_type):
- l(f" {field_name}:ptr {as_nim_prim_type(extract_ptr_type(field_type))}")
- elif is_func_ptr(field_type):
- l(f" {field_name}:proc({funcptr_args_c(field_type, prefix)}){funcptr_res_c(field_type)} {{.cdecl.}}")
- elif is_1d_array_type(field_type):
- array_type = extract_array_type(field_type)
- array_nums = extract_array_nums(field_type)
- if is_prim_type(array_type) or is_struct_type(array_type):
- if is_prim_type(array_type):
- nim_type = as_nim_prim_type(array_type)
- elif is_struct_type(array_type):
- nim_type = as_nim_struct_type(array_type, prefix)
- elif is_enum_type(array_type):
- nim_type = as_nim_enum_type(array_type, prefix)
- else:
- nim_type = '??? (array type)'
- t0 = f"array[{array_nums[0]}, {nim_type}]"
- t0_slice = f"[]const {nim_type}"
- t1 = f"[_]{nim_type}"
- l(f" {field_name}:{t0}")
- elif is_const_void_ptr(array_type):
- l(f" {field_name}:array[{array_nums[0]}, pointer]")
- else:
- l(f"// FIXME: ??? array {field_name}:{field_type} => {array_type} [{array_nums[0]}]")
- elif is_2d_array_type(field_type):
- array_type = extract_array_type(field_type)
- array_nums = extract_array_nums(field_type)
- if is_prim_type(array_type):
- nim_type = as_nim_prim_type(array_type)
- def_val = type_default_value(array_type)
- elif is_struct_type(array_type):
- nim_type = as_nim_struct_type(array_type, prefix)
- def_val = ".{ }"
- else:
- nim_type = "???"
- def_val = "???"
- t0 = f"array[{array_nums[0]}, array[{array_nums[1]}, {nim_type}]]"
- l(f" {field_name}:{t0}")
- else:
- l(f"// FIXME: {field_name}:{field_type};")
+ field_type = check_struct_field_type_override(decl['name'], field['name'], field['type'])
+ l(f" {field_name}:{as_nim_type(field_type, prefix)}")
l("")
def gen_consts(decl, prefix):
l("const")
for item in decl['items']:
- l(f" {trim_prefix(item['name'], prefix)}* = {item['value']}")
+ l(f" {as_camel_case(trim_prefix(item['name'], prefix), prefix)}* = {item['value']}")
l("")
-def gen_enum(decl, prefix):
+def gen_enum(decl, prefix, bitfield=None):
item_names_by_value = {}
value = -1
- hasForceU32 = False
- hasExplicitValues = False
+ has_force_u32 = False
+ has_explicit_values = False
for item in decl['items']:
itemName = item['name']
if itemName.endswith("_FORCE_U32"):
- hasForceU32 = True
+ has_force_u32 = True
elif itemName.endswith("_NUM"):
continue
else:
if 'value' in item:
- hasExplicitValues = True
+ has_explicit_values = True
value = int(item['value'])
else:
value += 1
item_names_by_value[value] = as_enum_item_name(item['name']);
- if hasForceU32:
- l(f"type {as_nim_enum_type(decl['name'], prefix)}* {{.pure, size:4.}} = enum")
+ enum_name = bitfield if bitfield is not None else decl['name']
+ enum_name_nim = as_nim_type_name(enum_name, prefix)
+ l('type')
+ if has_force_u32:
+ l(f" {enum_name_nim}* {{.pure, size:sizeof(cint).}} = enum")
else:
- l(f"type {as_nim_enum_type(decl['name'], prefix)}* {{.pure.}} = enum")
- if hasExplicitValues:
+ l(f" {enum_name_nim}* {{.pure.}} = enum")
+ if has_explicit_values:
# Nim requires explicit enum values to be declared in ascending order
for value in sorted(item_names_by_value):
name = item_names_by_value[value]
- l(f" {name} = {value},")
+ l(f" {name} = {value},")
else:
for name in item_names_by_value.values():
- l(f" {name},")
+ l(f" {name},")
+ if bitfield is not None:
+ l(f" {enum_name_nim}s = set[{enum_name_nim}]")
l("")
def gen_func_nim(decl, prefix):
c_func_name = decl['name']
nim_func_name = as_camel_case(decl['name'], prefix)
- nim_res_type = funcdecl_res_nim(decl, prefix)
- l(f"proc {nim_func_name}*({funcdecl_args_nim(decl, prefix)}):{funcdecl_res_nim(decl, prefix)} {{.cdecl, importc:\"{decl['name']}\".}}")
+ nim_res_type = funcdecl_res(decl, prefix)
+ l(f"proc {nim_func_name}*({funcdecl_args(decl, prefix)}):{funcdecl_res(decl, prefix)} {{.cdecl, importc:\"{decl['name']}\".}}")
l("")
def pre_parse(inp):
@@ -500,6 +448,9 @@ def pre_parse(inp):
enum_items[enum_name] = []
for item in decl['items']:
enum_items[enum_name].append(as_enum_item_name(item['name']))
+ for bitfield in const_bitfield_overrides.values():
+ enum_types.append(bitfield)
+ enum_types.append(bitfield + 's')
def gen_imports(inp, dep_prefixes):
for dep_prefix in dep_prefixes:
@@ -517,7 +468,11 @@ def gen_module(inp, dep_prefixes):
if not decl['is_dep']:
kind = decl['kind']
if kind == 'consts':
- gen_consts(decl, prefix)
+ bitfield = check_consts_bitfield_override(decl)
+ if bitfield is not None:
+ gen_enum(decl, prefix, bitfield=bitfield)
+ else:
+ gen_consts(decl, prefix)
elif kind == 'enum':
gen_enum(decl, prefix)
elif kind == 'struct':
@@ -530,33 +485,34 @@ def prepare():
print('Generating nim bindings:')
if not os.path.isdir('sokol-nim/src/sokol'):
os.makedirs('sokol-nim/src/sokol')
- if not os.path.isdir('sokol-nim/src/sokol/c'):
- os.makedirs('sokol-nim/src/sokol/c')
+ if not os.path.isdir('sokol-nim/src/sokol/gen'):
+ os.makedirs('sokol-nim/src/sokol/gen')
def gen(c_header_path, c_prefix, dep_c_prefixes):
+ if not c_prefix in module_names:
+ print(f'warning: skipping generation for {c_prefix} prefix...')
+ return
global out_lines
module_name = module_names[c_prefix]
c_source_path = c_source_paths[c_prefix]
print(f' {c_header_path} => {module_name}')
reset_globals()
- shutil.copyfile(c_header_path, f'sokol-nim/src/sokol/c/{os.path.basename(c_header_path)}')
+ shutil.copyfile(c_header_path, f'sokol-nim/src/sokol/gen/{os.path.basename(c_header_path)}')
ir = gen_ir.gen(c_header_path, c_source_path, module_name, c_prefix, dep_c_prefixes)
gen_module(ir, dep_c_prefixes)
output_path = f"sokol-nim/src/sokol/{ir['module']}.nim"
## some changes for readability
- out_lines = out_lines.replace("PixelformatInfo", "PixelFormatInfo")
- out_lines = out_lines.replace(" Dontcare,", " DontCare,")
- out_lines = out_lines.replace(" Vertexbuffer,", " VertexBuffer,")
- out_lines = out_lines.replace(" Indexbuffer,", " IndexBuffer,")
- out_lines = out_lines.replace(" N2d,", " Plane,")
- out_lines = out_lines.replace(" N3d,", " Volume,")
- out_lines = out_lines.replace(" Vs,", " Vertex,")
- out_lines = out_lines.replace(" Fs,", " Fragment,")
+ out_lines = out_lines.replace("pixelformatInfo", "pixelFormatInfo")
+ out_lines = out_lines.replace(" dontcare,", " dontCare,")
+ out_lines = out_lines.replace(" vertexbuffer,", " vertexBuffer,")
+ out_lines = out_lines.replace(" indexbuffer,", " indexBuffer,")
+ out_lines = out_lines.replace(" n2d,", " plane,")
+ out_lines = out_lines.replace(" n3d,", " volume,")
## include extensions in generated code
l("# Nim-specific API extensions")
- l(f"include nim/{ir['module']}")
+ l(f"include extra/{ir['module']}")
with open(output_path, 'w', newline='\n') as f_outp:
f_outp.write(out_lines)