Browse Source

gen_odin.py: initial function and enum bindings

Andre Weissflog 3 years ago
parent
commit
2ca5d33289
1 changed files with 64 additions and 22 deletions
  1. 64 22
      bindgen/gen_odin.py

+ 64 - 22
bindgen/gen_odin.py

@@ -122,10 +122,10 @@ def check_override(name, default=None):
 def check_ignore(name):
 def check_ignore(name):
     return name in ignores
     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):
 def as_snake_case(s, prefix):
-    outp = s.lower()
-    if outp.startswith(prefix):
+    outp = s
+    if outp.lower().startswith(prefix):
         outp = outp[len(prefix):]
         outp = outp[len(prefix):]
     return outp
     return outp
 
 
@@ -228,7 +228,7 @@ def extract_ptr_type(s):
     else:
     else:
         return tokens[0]
         return tokens[0]
 
 
-def as_extern_c_arg_type(arg_type, prefix):
+def as_c_arg_type(arg_type, prefix):
     if arg_type == "void":
     if arg_type == "void":
         return ""
         return ""
     elif is_prim_type(arg_type):
     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):
     elif is_const_prim_ptr(arg_type):
         return f"^{as_prim_type(extract_ptr_type(arg_type))}"
         return f"^{as_prim_type(extract_ptr_type(arg_type))}"
     else:
     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):
 def as_odin_arg_type(arg_type, prefix):
     if arg_type == "void":
     if arg_type == "void":
         return ""
         return ""
     elif is_prim_type(arg_type):
     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):
     elif is_struct_type(arg_type):
         return as_struct_or_enum_type(arg_type, prefix)
         return as_struct_or_enum_type(arg_type, prefix)
     elif is_enum_type(arg_type):
     elif is_enum_type(arg_type):
@@ -285,7 +292,7 @@ def funcdecl_args_c(decl, prefix):
             s += ', '
             s += ', '
         param_name = param_decl['name']
         param_name = param_decl['name']
         param_type = check_override(f'{func_name}.{param_name}', default=param_decl['type'])
         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
     return s
 
 
 def funcdecl_args_odin(decl, prefix):
 def funcdecl_args_odin(decl, prefix):
@@ -303,17 +310,13 @@ def funcdecl_result_c(decl, prefix):
     func_name = decl['name']
     func_name = decl['name']
     decl_type = decl['type']
     decl_type = decl['type']
     res_c_type = decl_type[:decl_type.index('(')].strip()
     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):
 def funcdecl_result_odin(decl, prefix):
     func_name = decl['name']
     func_name = decl['name']
     decl_type = decl['type']
     decl_type = decl['type']
     res_c_type = decl_type[:decl_type.index('(')].strip()
     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):
 def gen_c_imports(inp):
     l(f'// FIXME: foreign import...\n')
     l(f'// FIXME: foreign import...\n')
@@ -323,27 +326,66 @@ def gen_c_imports(inp):
     for decl in inp['decls']:
     for decl in inp['decls']:
         if decl['kind'] == 'func' and not decl['is_dep'] and not check_ignore(decl['name']):
         if decl['kind'] == 'func' and not decl['is_dep'] and not check_ignore(decl['name']):
             args = funcdecl_args_c(decl, prefix)
             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('}')
     l('}')
 
 
 def gen_consts(decl, prefix):
 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):
 def gen_struct(decl, prefix):
     # FIXME
     # FIXME
     l(f'// FIXME: struct {decl["name"]}')
     l(f'// FIXME: struct {decl["name"]}')
 
 
 def gen_enum(decl, prefix):
 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):
 def gen_func(decl, prefix):
+    c_func_name = decl['name']
     args = funcdecl_args_odin(decl, prefix)
     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('}')
     l('}')
 
 
 def gen_module(inp, dep_prefixes):
 def gen_module(inp, dep_prefixes):