moc.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. mapping = {
  2. 'int': 'i64',
  3. 'float': 'f64',
  4. 'str': 'const char*',
  5. 'bool': 'bool',
  6. 'None': 'void'
  7. }
  8. def args(n, a: list, res: list, first=True):
  9. if n == 0:
  10. # 3 args must be the same type
  11. if len(a) == 4 and len(set(a[1:])) != 1:
  12. return
  13. res.append(tuple(a))
  14. return
  15. for p_ret, c_ret in mapping.items():
  16. if not first and p_ret == 'None':
  17. continue
  18. a.append(p_ret)
  19. args(n-1, a, res, first=False)
  20. a.pop()
  21. data = []
  22. for n in [4,3,2,1]:
  23. res = []
  24. args(n, [], res)
  25. for p_ret,*p_args in res:
  26. c_args = [mapping[i] for i in p_args]
  27. c_ret = mapping[p_ret]
  28. name = f'__f_{p_ret}__{"_".join(p_args)}'
  29. # if c_ret == 'const char*':
  30. # c_ret = 'char*'
  31. s = f'typedef {c_ret} (*{name})({", ".join(c_args)});'
  32. s += '\n'
  33. impl = []
  34. for i, p_arg in enumerate(p_args):
  35. impl.append( f'{mapping[p_arg]} _{i} = vm->Py{p_arg.capitalize()}_AS_C(args[{i}]);' )
  36. call_impl = f'f({", ".join([f"_{j}" for j in range(len(p_args))])})';
  37. if p_ret == 'None':
  38. impl.append( call_impl + ';' )
  39. impl.append( 'return vm->None;' )
  40. else:
  41. impl.append ( f'{mapping[p_ret]} ret = {call_impl};' )
  42. impl.append( f'return vm->Py{p_ret.capitalize()}(ret);' )
  43. impl = '\n'.join([' '*8 + i for i in impl])
  44. s += f'''__EXPORT\nvoid pkpy_vm_bind{name[3:]}(VM* vm, const char* mod, const char* name, {name} f) {{
  45. PyVar obj = vm->new_module_if_not_existed(mod);
  46. vm->bindFunc<{len(p_args)}>(obj, name, [f](VM* vm, const pkpy::ArgList& args) {{
  47. {impl}
  48. }});
  49. }}''' + '\n'
  50. data.append(s)
  51. with open('src/_bindings.h', 'w') as f:
  52. text = '\n'.join(data)
  53. f.write('extern "C" {\n' + text + '}')