aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2022-07-16 16:27:03 +0200
committerAndre Weissflog <floooh@gmail.com>2022-07-16 16:27:03 +0200
commit2ca5d33289a450a1ef8bd2bbd8e00e90aa401321 (patch)
tree5543a617a316ee0b22f6a831f4519106d57d11d5
parentb893bef654c0424c6a2cce7b95707cf296ff2bd0 (diff)
gen_odin.py: initial function and enum bindings
-rw-r--r--bindgen/gen_odin.py86
1 files changed, 64 insertions, 22 deletions
diff --git a/bindgen/gen_odin.py b/bindgen/gen_odin.py
index 4cdec5e5..9a06bb66 100644
--- a/bindgen/gen_odin.py
+++ b/bindgen/gen_odin.py
@@ -122,10 +122,10 @@ def check_override(name, default=None):
def check_ignore(name):
return name in ignores
-# PREFIX_BLA_BLUB to bla_blub
+# PREFIX_BLA_BLUB to BLA_BLUB, prefix_bla_blub to bla_blub
def as_snake_case(s, prefix):
- outp = s.lower()
- if outp.startswith(prefix):
+ outp = s
+ if outp.lower().startswith(prefix):
outp = outp[len(prefix):]
return outp
@@ -228,7 +228,7 @@ def extract_ptr_type(s):
else:
return tokens[0]
-def as_extern_c_arg_type(arg_type, prefix):
+def as_c_arg_type(arg_type, prefix):
if arg_type == "void":
return ""
elif is_prim_type(arg_type):
@@ -250,13 +250,20 @@ def as_extern_c_arg_type(arg_type, prefix):
elif is_const_prim_ptr(arg_type):
return f"^{as_prim_type(extract_ptr_type(arg_type))}"
else:
- sys.exit(f"Error as_extern_c_arg_type(): {arg_type}")
+ sys.exit(f"Error as_c_arg_type(): {arg_type}")
def as_odin_arg_type(arg_type, prefix):
if arg_type == "void":
return ""
elif is_prim_type(arg_type):
- return as_prim_type(arg_type)
+ # for args and return values we'll map the C int type (32-bit) to Odin's pointer-sized int type,
+ # and the C bool type to Odin's 'unsized' bool type
+ if arg_type == 'int':
+ return 'int'
+ elif arg_type == 'bool':
+ return 'bool'
+ else:
+ return as_prim_type(arg_type)
elif is_struct_type(arg_type):
return as_struct_or_enum_type(arg_type, prefix)
elif is_enum_type(arg_type):
@@ -285,7 +292,7 @@ def funcdecl_args_c(decl, prefix):
s += ', '
param_name = param_decl['name']
param_type = check_override(f'{func_name}.{param_name}', default=param_decl['type'])
- s += f"{param_name}: {as_extern_c_arg_type(param_type, prefix)}"
+ s += f"{param_name}: {as_c_arg_type(param_type, prefix)}"
return s
def funcdecl_args_odin(decl, prefix):
@@ -303,17 +310,13 @@ def funcdecl_result_c(decl, prefix):
func_name = decl['name']
decl_type = decl['type']
res_c_type = decl_type[:decl_type.index('(')].strip()
- result_type = as_extern_c_arg_type(check_override(f'{func_name}.RESULT', default=res_c_type), prefix)
- arrow = '' if result_type == '' else '-> '
- return f'{arrow}{result_type}'
+ return as_c_arg_type(check_override(f'{func_name}.RESULT', default=res_c_type), prefix)
def funcdecl_result_odin(decl, prefix):
func_name = decl['name']
decl_type = decl['type']
res_c_type = decl_type[:decl_type.index('(')].strip()
- result_type = as_odin_arg_type(check_override(f'{func_name}.RESULT', default=res_c_type), prefix)
- arrow = '' if result_type == '' else '-> '
- return f'{arrow}{result_type}'
+ return as_odin_arg_type(check_override(f'{func_name}.RESULT', default=res_c_type), prefix)
def gen_c_imports(inp):
l(f'// FIXME: foreign import...\n')
@@ -323,27 +326,66 @@ def gen_c_imports(inp):
for decl in inp['decls']:
if decl['kind'] == 'func' and not decl['is_dep'] and not check_ignore(decl['name']):
args = funcdecl_args_c(decl, prefix)
- ret = funcdecl_result_c(decl, prefix)
- l(f" {decl['name']} :: proc({args}) {ret} ---")
+ ret_type = funcdecl_result_c(decl, prefix)
+ ret_str = '' if ret_type == '' else f'-> {ret_type}'
+ l(f" {decl['name']} :: proc({args}) {ret_str} ---")
l('}')
def gen_consts(decl, prefix):
- # FIXME
- l(f'// FIXME: consts')
+ for item in decl['items']:
+ item_name = check_override(item['name'])
+ l(f"{as_snake_case(item_name, prefix)} :: {item['value']};")
def gen_struct(decl, prefix):
# FIXME
l(f'// FIXME: struct {decl["name"]}')
def gen_enum(decl, prefix):
- # FIXME
- l(f'// FIXME: enum {decl["name"]}')
+ enum_name = check_override(decl['name'])
+ l(f'{as_struct_or_enum_type(enum_name, prefix)} :: enum i32 {{')
+ for item in decl['items']:
+ item_name = as_enum_item_name(check_override(item['name']))
+ if item_name != 'FORCE_U32':
+ if 'value' in item:
+ l(f" {item_name} = {item['value']},")
+ else:
+ l(f" {item_name},")
+ l('};')
def gen_func(decl, prefix):
+ c_func_name = decl['name']
args = funcdecl_args_odin(decl, prefix)
- ret = funcdecl_result_odin(decl, prefix)
- l(f"{as_snake_case(decl['name'], prefix)} :: proc({args}) {ret} {{")
- l(' // FIXME')
+ ret_type = funcdecl_result_odin(decl, prefix)
+ ret_str = '' if ret_type == '' else f'-> {ret_type}'
+ if ret_type != funcdecl_result_c(decl, prefix):
+ # cast needed for return type
+ ret_cast = f'cast({ret_type})'
+ else:
+ ret_cast = ''
+ l(f"{as_snake_case(decl['name'], prefix)} :: proc({args}) {ret_str} {{")
+ s = ' '
+ if ret_type == '':
+ # void result
+ s += f"{c_func_name}("
+ else:
+ s += f"return {ret_cast}{c_func_name}("
+ for i, param_decl in enumerate(decl['params']):
+ if i > 0:
+ s += ', '
+ arg_name = param_decl['name']
+ arg_type = param_decl['type']
+ if is_const_struct_ptr(arg_type):
+ s += f"&{arg_name}"
+ else:
+ odin_arg_type = as_odin_arg_type(arg_type, prefix)
+ c_arg_type = as_c_arg_type(arg_type, prefix)
+ if odin_arg_type != c_arg_type:
+ cast = f'cast({c_arg_type})'
+ else:
+ cast = ''
+ s += f'{cast}{arg_name}'
+ s += ');'
+ l(s)
l('}')
def gen_module(inp, dep_prefixes):