343 lines
9.4 KiB
JavaScript
Executable File
343 lines
9.4 KiB
JavaScript
Executable File
// a crappy dear_binding -> odin generator
|
|
const file = await Bun.file('glfw/impl_glfw.json').json()
|
|
|
|
const keywords =['asm','auto_cast','bit_set','break','case','cast','context','continue',
|
|
'defer','distinct','do','dynamic','else','enum','fallthrough','for','foreign','if',
|
|
'import','in','map','not_in','or_else','or_return','package','proc','return','struct',
|
|
'switch','transmute','typeid','union','using','when','where'];
|
|
const namespace = {} // [c-name]: odin-name
|
|
|
|
console.log(`package imgui\n
|
|
foreign import imgui "!!!!!!!!!!!!!"
|
|
`)
|
|
|
|
for (const en of file.enums) {
|
|
let name = en.name;
|
|
if (name.startsWith('ImGui'))
|
|
name = name.substring(5)
|
|
if (name.endsWith('_'))
|
|
name = name.substring(0, name.length - 1)
|
|
|
|
let out = `${name} :: enum {`
|
|
for (const el of en.elements) {
|
|
let el_name = el.name
|
|
if (el_name.startsWith(en.name)) el_name = el_name.substring(en.name.length)
|
|
if (el_name.startsWith('_')) el_name = el_name.substring(1)
|
|
if (el_name.match(/^\d/)) el_name = 'Num' + el_name
|
|
out += `\n\t${el_name}`;
|
|
if (el.value !== undefined) {
|
|
let v = el.value
|
|
// if (el.value_expression.startsWith(en.name)) ve = el_name.substring(en.name.length)
|
|
out += ` = ${v}`
|
|
}
|
|
out += ','
|
|
}
|
|
out += '\n}'
|
|
console.log(out)
|
|
if (en.name.endsWith('_')) namespace[en.name.substring(0, en.name.length - 1)] = name
|
|
else namespace[en.name] = name
|
|
}
|
|
|
|
// see odin core:c
|
|
const cToOdinTypes = {
|
|
'int': 'i32',
|
|
'signed char': 'i8',
|
|
'unsigned char': 'u8',
|
|
'short': 'i16',
|
|
'signed short': 'i16',
|
|
'unsigned short': 'u16',
|
|
'signed int': 'i32',
|
|
'unsigned int': 'u32',
|
|
'long long': 'i64',
|
|
'signed long long': 'i64',
|
|
'unsigned long long': 'u64',
|
|
'void*': 'rawptr',
|
|
'const void*': 'rawptr',
|
|
'size_t': 'u32',
|
|
'ssize_t': 'i32',
|
|
'const char*': 'cstring',
|
|
'char*': 'cstring',
|
|
'unsigned char*': 'cstring',
|
|
'bool': 'b8',
|
|
'float': 'f32',
|
|
'double': 'f64',
|
|
}
|
|
|
|
const fp_typedef = []
|
|
for (const td of file.typedefs) {
|
|
if (namespace[td.name]) continue
|
|
let name = td.name;
|
|
if (name.startsWith('ImGui'))
|
|
name = name.substring(5)
|
|
|
|
let decl = td.type.declaration;
|
|
if (decl in cToOdinTypes)
|
|
decl = cToOdinTypes[decl];
|
|
|
|
if (td.type.type_details?.flavour === 'function_pointer') {
|
|
const fp_return_type = td.type.type_details.return_type.declaration
|
|
const args = []
|
|
for (const arg of td.type.type_details.arguments) {
|
|
let type = '';
|
|
if (arg.type.declaration in cToOdinTypes)
|
|
type = cToOdinTypes[arg.type.declaration]
|
|
else {
|
|
let innerType = arg.type.description
|
|
while (innerType.kind === 'Pointer') {
|
|
type += '^'
|
|
innerType = innerType.inner_type
|
|
}
|
|
if (innerType.name in namespace)
|
|
type += namespace[innerType.name]
|
|
else
|
|
{
|
|
type += innerType.name
|
|
}
|
|
}
|
|
// args.push(`${arg.name}: ${type}`)
|
|
args.push({
|
|
name: arg.name,
|
|
type: type,
|
|
})
|
|
}
|
|
|
|
let return_type = null
|
|
if (fp_return_type !== 'void'){
|
|
if (fp_return_type in cToOdinTypes)
|
|
return_type = cToOdinTypes[fp_return_type]
|
|
else {
|
|
let innerType = td.type.type_details.return_type
|
|
while (innerType.kind === 'Pointer') {
|
|
return_type += '^'
|
|
innerType = innerType.inner_type
|
|
}
|
|
// return_type += innerType.name
|
|
}
|
|
}
|
|
fp_typedef.push({
|
|
name: name,
|
|
args: args,
|
|
return_type: return_type,
|
|
})
|
|
|
|
} else {
|
|
console.log(`${name} :: ${decl}`)
|
|
}
|
|
namespace[td.name] = name
|
|
}
|
|
|
|
|
|
for (const fptd of fp_typedef) {
|
|
let sep = ''
|
|
let out = fptd.name
|
|
out += ` :: proc(`
|
|
for (const arg of fptd.args) {
|
|
let type = arg.type
|
|
if (arg.type in namespace) type = namespace[arg.type]
|
|
out += `${sep}${arg.name}: ${type}`
|
|
sep = ', '
|
|
}
|
|
out += `)`
|
|
if (fptd.return_type !== null) out += ` -> ${fptd.return_type}`
|
|
console.log(out)
|
|
}
|
|
|
|
console.log(`@(default_calling_convention = "cdecl", link_prefix = "ImGui_")
|
|
foreign imgui {`)
|
|
|
|
for (const fn of file.functions) {
|
|
let name = fn.name;
|
|
if (name.startsWith('ImGui_')) name = name.substring(6)
|
|
|
|
const args = []
|
|
for (const arg of fn.arguments) {
|
|
let type = '';
|
|
let name = (keywords.includes(arg.name))? '_' + arg.name: arg.name
|
|
if (arg.is_varargs){
|
|
name = '#c_vararg ' + name
|
|
type = '..any'
|
|
}
|
|
else {
|
|
if (arg.type.declaration in cToOdinTypes)
|
|
type = cToOdinTypes[arg.type.declaration]
|
|
else if (arg.type.declaration in namespace) {
|
|
if (namespace[arg.type.declaration].startsWith('ImGui'))
|
|
type = namespace[arg.type.declaration].substring('ImGui'.length)
|
|
else
|
|
type = namespace[arg.type.declaration]
|
|
|
|
}
|
|
else {
|
|
|
|
let innerType = arg.type.description
|
|
if (arg.is_array) {
|
|
type += `[${innerType.bounds ?? ''}]`
|
|
innerType = innerType.inner_type
|
|
}
|
|
let ptr = 0
|
|
let ptr_chr = '^'
|
|
while (innerType.kind === 'Pointer') {
|
|
ptr++
|
|
innerType = innerType.inner_type
|
|
}
|
|
if (ptr && innerType.builtin_type == 'void' || innerType.builtin_type?.endsWith('char')) {
|
|
ptr--
|
|
ptr_chr = '[^]'
|
|
}
|
|
for (let i = 0; i < ptr; i++) {
|
|
type += ptr_chr
|
|
}
|
|
|
|
if (ptr_chr === '[^]') {
|
|
if (innerType.builtin_type == 'void') type += 'rawptr'
|
|
else if (innerType.builtin_type.endsWith('char')) type += 'cstring'
|
|
}
|
|
else if (innerType.name in namespace) type += namespace[innerType.name]
|
|
else if (innerType.name in cToOdinTypes) type += cToOdinTypes[innerType.name]
|
|
else if (innerType.builtin_type in cToOdinTypes) type += cToOdinTypes[innerType.builtin_type]
|
|
else if (innerType.builtin_type?.replace('_',' ') in cToOdinTypes) type += cToOdinTypes[innerType.builtin_type.replace('_',' ')]
|
|
else if (innerType.name) {
|
|
if (innerType.name.startsWith('ImGui'))
|
|
type += innerType.name.substring('ImGui'.length)
|
|
else
|
|
type += innerType.name
|
|
}
|
|
else type = '[!!!]'
|
|
}
|
|
}
|
|
// args.push(`${arg.name}: ${type}`)
|
|
args.push({
|
|
name: name, // do a keyword check instead
|
|
type: type,
|
|
})
|
|
}
|
|
|
|
let sep = ''
|
|
let out = name
|
|
out += ` :: proc(`
|
|
for (const arg of args) {
|
|
let type = arg.type
|
|
if (arg.type in namespace) type = namespace[arg.type]
|
|
out += `${sep}${arg.name}: ${type}`
|
|
sep = ', '
|
|
}
|
|
out += `)`
|
|
|
|
if (fn.return_type.declaration !== 'void'){
|
|
let return_type = ''
|
|
if (fn.return_type in cToOdinTypes)
|
|
return_type = cToOdinTypes[fp_return_type]
|
|
else if (fn.return_type in namespace) {
|
|
if (namespace[fn.return_type].startsWith('ImGui'))
|
|
return_type = namespace[fn.return_type].substring('ImGui'.length)
|
|
}
|
|
else {
|
|
let innerType = fn.return_type.description
|
|
let ptr = 0
|
|
let ptr_chr = '^'
|
|
while (innerType.kind === 'Pointer') {
|
|
ptr++
|
|
innerType = innerType.inner_type
|
|
}
|
|
if (ptr && innerType.builtin_type == 'void' || innerType.builtin_type == 'char') {
|
|
ptr--
|
|
ptr_chr = '[^]'
|
|
}
|
|
for (let i = 0; i < ptr; i++) {
|
|
return_type += ptr_chr
|
|
}
|
|
|
|
if (ptr_chr === '[^]') {
|
|
if (innerType.builtin_type == 'void') return_type += 'rawptr'
|
|
else if (innerType.builtin_type == 'char') return_type += 'cstring'
|
|
}
|
|
|
|
else if (innerType.name in namespace) {
|
|
if (namespace[innerType.name].startsWith('ImGui'))
|
|
return_type += namespace[innerType.name].substring('ImGui'.length)
|
|
else
|
|
return_type += namespace[innerType.name]
|
|
}
|
|
else if (innerType.name in cToOdinTypes) return_type += cToOdinTypes[innerType.name]
|
|
else if (innerType.builtin_type in cToOdinTypes) return_type += cToOdinTypes[innerType.builtin_type]
|
|
else if (innerType.builtin_type?.replace('_',' ') in cToOdinTypes) return_type += cToOdinTypes[innerType.builtin_type.replace('_',' ')]
|
|
else if (innerType.name) {
|
|
if (innerType.name.startsWith('ImGui'))
|
|
return_type += innerType.name.substring('ImGui'.length)
|
|
else
|
|
return_type += innerType.name
|
|
}
|
|
else return_type = '[!!!]'
|
|
}
|
|
|
|
out += ` -> ${return_type}`
|
|
}
|
|
out += ` ---`
|
|
console.log('\t'+out)
|
|
namespace[fn.name] = name
|
|
|
|
}
|
|
console.log('}')
|
|
|
|
for (const struct of file.structs) {
|
|
let name = struct.name;
|
|
if (name.startsWith('ImGui'))
|
|
name = name.substring(5)
|
|
|
|
namespace[struct.name] = name
|
|
|
|
let out = `${name} :: struct {\n`;
|
|
for (const field of struct.fields) {
|
|
out += '\t'
|
|
out += field.name
|
|
out += ': '
|
|
let innerType = field.type.description
|
|
if (field.is_array) {
|
|
let bound = innerType.bounds
|
|
// bleh
|
|
if (innerType.bounds.startsWith('ImGui')) {
|
|
bound = bound.substring('ImGui'.length)
|
|
if (bound.split('_')[0] in namespace)
|
|
bound = bound.split('_')[1]
|
|
else
|
|
bound = innerType.bounds
|
|
}
|
|
out += `[${bound ?? ''}]`
|
|
innerType = innerType.inner_type
|
|
}
|
|
let ptr = 0
|
|
let ptr_chr = '^'
|
|
while (innerType.kind === 'Pointer') {
|
|
ptr++
|
|
innerType = innerType.inner_type
|
|
}
|
|
if (ptr && innerType.builtin_type == 'void' || innerType.builtin_type?.endsWith('char')) {
|
|
ptr--
|
|
ptr_chr = '[^]'
|
|
}
|
|
for (let i = 0; i < ptr; i++) {
|
|
out += ptr_chr
|
|
}
|
|
if (ptr_chr === '[^]') {
|
|
if (innerType.builtin_type == 'void') out += 'rawptr'
|
|
else if (innerType.builtin_type.endsWith('char')) out += 'cstring'
|
|
}
|
|
else if (innerType.name in namespace) out += namespace[innerType.name]
|
|
else if (innerType.name in cToOdinTypes) out += cToOdinTypes[innerType.name]
|
|
else if (innerType.builtin_type in cToOdinTypes) out += cToOdinTypes[innerType.builtin_type]
|
|
else if (innerType.builtin_type?.replace('_',' ') in cToOdinTypes) out += cToOdinTypes[innerType.builtin_type.replace('_',' ')]
|
|
else if (innerType.name) {
|
|
if (innerType.name.startsWith('ImGui'))
|
|
out += innerType.name.substring('ImGui'.length)
|
|
else
|
|
out += innerType.name
|
|
}
|
|
|
|
out += ',\n'
|
|
}
|
|
out += '}'
|
|
console.log(out)
|
|
}
|
|
|
|
|