rayjs/generate_bindings.js

147 lines
3.4 KiB
JavaScript
Raw Normal View History

2023-05-04 15:00:22 +00:00
// Run with Node.js
const fs = require('fs');
2023-05-04 21:54:03 +00:00
const { connect } = require('http2');
let api, modules
2023-05-04 15:00:22 +00:00
async function main(){
api = await readJson('thirdparty/raylib/parser/output/raylib_api.json')
2023-05-04 21:54:03 +00:00
modules = await readJson('bindings.json')
2023-05-04 15:00:22 +00:00
2023-05-04 21:54:03 +00:00
const headers = modules.map(generateModule)
2023-05-04 15:00:22 +00:00
2023-05-04 21:54:03 +00:00
modules.forEach(async (header,i) => {
await writeFile(`src/bindings/js_${header.name}.h`, headers[i])
2023-05-04 15:00:22 +00:00
});
}
class FunctionList {
definitions = []
2023-05-04 15:05:36 +00:00
addFunctionDef(name, args, cname){
2023-05-04 21:54:03 +00:00
this.definitions.push(`JS_CFUNC_DEF("${name}", ${args}, ${cname})`)
2023-05-04 15:05:36 +00:00
}
addIntConst(name, val){
this.definitions.push(`JS_PROP_INT32_DEF("${name}", ${val})`)
2023-05-04 15:00:22 +00:00
}
2023-05-04 21:54:03 +00:00
generate(name){
return `static const JSCFunctionListEntry js_${name}_funcs[] = {
${this.definitions.map(x => " "+x).join(",\n")}
};`
}
2023-05-04 15:00:22 +00:00
}
const generateModule = (mod) => {
2023-05-04 21:54:03 +00:00
const fl = new FunctionList()
let content = mod.functions.map(generateFunction(fl)).join("\n\n")
content += "\n\n" + fl.generate(mod.name)
return generateHeader(mod.name, content)
2023-05-04 15:00:22 +00:00
}
2023-05-04 21:54:03 +00:00
const generateFunction = (functionList) => (func) => {
2023-05-04 15:00:22 +00:00
const api = findFunction(func.name)
2023-05-04 21:54:03 +00:00
const cfunc = new CFunction(func, api, functionList)
return cfunc.generate()
}
const generateParameter = (param,i) => {
switch(param.type){
case "const char *":
return `${param.type} ${param.name} = JS_ToCString(ctx, argv[${i}]);`
case "int":
return `${param.type} ${param.name};\n JS_ToInt32(ctx, &${param.name}, argv[${i}]);`
}
}
class CFunction {
constructor(func, api, functionList){
this.func = func
this.api = api
this.functionList = functionList
this.functionName = `js_${func.jsName}`
}
generateParameters(){
return this.api.params.map(generateParameter)
}
generate(){
this.functionList.addFunctionDef(this.func.jsName, this.api.params.length, this.functionName)
return `static JSValue ${this.functionName}(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){
${this.generateParameters().map(x => " "+x).join("\n")}
return JS_UNDEFINED;
}`
}
2023-05-04 15:00:22 +00:00
}
const findFunction = (name) => findIn(api.functions,name)
const findIn = (arr, name) => arr.find(x => x.name == name)
async function readJson(path){
const c = await readFile(path)
return JSON.parse(c)
}
function readFile(path) {
const p = new Promise((res,rej) => {
fs.readFile(path, 'utf8', (err,data) => {
if(err) rej(error)
else res(data)
})
})
return p
}
function writeFile(path, data){
return new Promise((res, rej) => {
fs.writeFile(path, data, (err) => {
if(err) rej(err)
else res()
})
})
}
2023-05-04 21:54:03 +00:00
function generateHeader(name, content){
return `
2023-05-04 15:00:22 +00:00
#ifndef JS_${name}
#define JS_${name}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <quickjs.h>
2023-05-04 21:54:03 +00:00
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
2023-05-04 15:00:22 +00:00
${content}
static int js_${name}_init(JSContext *ctx, JSModuleDef *m){
JS_SetModuleExportList(ctx, m, js_${name}_funcs,
countof(js_${name}_funcs));
}
JSModuleDef *js_init_module_${name}(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_${name}_init);
if (!m)
return NULL;
2023-05-04 21:54:03 +00:00
JS_AddModuleExportList(ctx, m, js_${name}_funcs,
countof(js_${name}_funcs));
2023-05-04 15:00:22 +00:00
return m;
}
#endif
`
}
main()