mirror of https://github.com/mode777/rayjs.git
Add getter generation
This commit is contained in:
parent
d9f10bed4f
commit
fd97c55510
|
@ -150,7 +150,7 @@ export abstract class GenericCodeGenerator<T extends CodeGenerator> {
|
|||
this.tokens.push(Token.UNINDENT)
|
||||
}
|
||||
|
||||
public function(name: string, returnType: string, args: FunctionArgument[], isStatic: boolean, func?: (gen: T) => void){
|
||||
public function(name: string, returnType: string, args: FunctionArgument[], isStatic: boolean, func?: (gen: T) => void): T {
|
||||
const sub = this.createGenerator();
|
||||
sub.setTag("_type", "function-body")
|
||||
sub.setTag("_name", name)
|
||||
|
|
|
@ -15,7 +15,7 @@ function main(){
|
|||
core_gen.writeTo("src/bindings/js_raylib_core.h")
|
||||
|
||||
const texture_gen = new RayLibHeader("raylib_texture", apiDesc)
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage")
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage", { properties: { width: { get: true } } })
|
||||
texture_gen.writeTo("src/bindings/js_raylib_texture.h")
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ export class QuickJsHeader {
|
|||
}
|
||||
}
|
||||
|
||||
export abstract class GenericQuickJsGenerator<T extends CodeGenerator> extends GenericCodeGenerator<T> {
|
||||
export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extends GenericCodeGenerator<T> {
|
||||
|
||||
jsBindingFunction(jsName: string){
|
||||
const args = [
|
||||
|
@ -69,16 +69,27 @@ export abstract class GenericQuickJsGenerator<T extends CodeGenerator> extends G
|
|||
return sub
|
||||
}
|
||||
|
||||
jsReadParameter(type: string, name: string, index: number){
|
||||
jsToC(type: string, name: string, src: string){
|
||||
this.inline(`${type} ${name}`)
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(` = JS_ToCString(ctx, argv[${index}])`)
|
||||
this.statement(` = JS_ToCString(ctx, ${src})`)
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`)
|
||||
break;
|
||||
case "int":
|
||||
this.statement('')
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, argv[${index}])`)
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`)
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type)
|
||||
}
|
||||
}
|
||||
|
||||
jsToJs(type: string, name: string, src: string){
|
||||
this.inline(`JSValue ${name}`)
|
||||
switch (type) {
|
||||
case "int":
|
||||
this.statement(` = JS_NewInt32(ctx, ${src})`)
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type)
|
||||
|
@ -121,6 +132,10 @@ export abstract class GenericQuickJsGenerator<T extends CodeGenerator> extends G
|
|||
this.line(`JS_PROP_STRING_DEF("${key}","${value}", JS_PROP_CONFIGURABLE),`)
|
||||
}
|
||||
|
||||
jsGetSetDef(key: string, getFunc?: string, setFunc?: string){
|
||||
this.line(`JS_CGETSET_DEF("${key}",${getFunc || "NULL"},${setFunc || "NULL"}),`)
|
||||
}
|
||||
|
||||
jsStructFinalizer(classId: string, structName: string, onFinalize?: (gen: T, ptrName: string) => void){
|
||||
const args = [{type: "JSRuntime *", name: "rt"},{type: "JSValue", name: "val"}]
|
||||
const body = this.function(`js_${structName}_finalizer`, "void", args, true)
|
||||
|
@ -154,8 +169,9 @@ export abstract class GenericQuickJsGenerator<T extends CodeGenerator> extends G
|
|||
cond.returnExp("JS_EXCEPTION")
|
||||
})
|
||||
fun.declare(field, type, false, "ptr->"+field)
|
||||
// TODO: to JS
|
||||
fun.jsToJs(type, "ret", field)
|
||||
fun.returnExp("ret")
|
||||
return fun
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { ApiDescription, ApiFunction, ApiStruct } from "./api"
|
||||
import { CodeGenerator } from "./generation"
|
||||
import { QuickJsHeader } from "./quickjs"
|
||||
|
||||
export interface StructBindingOptions {
|
||||
getters?: string[]
|
||||
setters?: string[]
|
||||
properties?: { [key:string]: { get?:boolean, set?:boolean } }
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
// read parameters
|
||||
for (let i = 0; i < api.params.length; i++) {
|
||||
const para = api.params[i]
|
||||
fun.jsReadParameter(para.type,para.name,i)
|
||||
fun.jsToC(para.type,para.name,"argv["+i+"]")
|
||||
}
|
||||
// call c function
|
||||
fun.call(api.name, api.params.map(x => x.name), api.returnType === "void" ? null : {type: api.returnType, name: "returnVal"})
|
||||
|
@ -33,8 +33,8 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
if(api.returnType === "void"){
|
||||
fun.statement("return JS_UNDEFINED")
|
||||
} else {
|
||||
// TODO: Convert to JS
|
||||
fun.statement("return retVal")
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal")
|
||||
fun.returnExp("returnVal")
|
||||
}
|
||||
|
||||
// add binding to function declaration
|
||||
|
@ -51,8 +51,22 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
const classId = this.declarations.jsClassId(`js_${struct.name}_class_id`)
|
||||
|
||||
const finalizer = this.structs.jsStructFinalizer(classId, struct.name, (gen,ptr) => destructor && gen.call(destructor.name, ["*"+ptr]))
|
||||
//TODO: declareGetterSetter()
|
||||
|
||||
const propDeclarations = this.structs.createGenerator()
|
||||
if(options && options.properties){
|
||||
for (const field of Object.keys(options.properties)) {
|
||||
const type = struct.fields.find(x => x.name === field)?.type
|
||||
if(!type) throw new Error(`Struct ${struct.name} does not contain field ${field}`)
|
||||
const el = options.properties[field]
|
||||
let _get: CodeGenerator | undefined = undefined
|
||||
let _set: CodeGenerator | undefined = undefined
|
||||
if(el.get) _get = this.structs.jsStructGetter(struct.name, classId, field, type)
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), undefined)
|
||||
}
|
||||
}
|
||||
|
||||
const classFuncList = this.structs.jsFunctionList(`js_${struct.name}_proto_funcs`)
|
||||
classFuncList.child(propDeclarations)
|
||||
classFuncList.jsPropStringDef("[Symbol.toStringTag]", "Image")
|
||||
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"))
|
||||
|
||||
|
|
|
@ -332,16 +332,26 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
const sub = this.function("js_" + jsName, "JSValue", args, true);
|
||||
return sub;
|
||||
}
|
||||
jsReadParameter(type, name, index) {
|
||||
jsToC(type, name, src) {
|
||||
this.inline(`${type} ${name}`);
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(` = JS_ToCString(ctx, argv[${index}])`);
|
||||
this.statement(` = JS_ToCString(ctx, ${src})`);
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`);
|
||||
break;
|
||||
case "int":
|
||||
this.statement('');
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, argv[${index}])`);
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
}
|
||||
}
|
||||
jsToJs(type, name, src) {
|
||||
this.inline(`JSValue ${name}`);
|
||||
switch (type) {
|
||||
case "int":
|
||||
this.statement(` = JS_NewInt32(ctx, ${src})`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
|
@ -378,6 +388,9 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
jsPropStringDef(key, value) {
|
||||
this.line(`JS_PROP_STRING_DEF("${key}","${value}", JS_PROP_CONFIGURABLE),`);
|
||||
}
|
||||
jsGetSetDef(key, getFunc, setFunc) {
|
||||
this.line(`JS_CGETSET_DEF("${key}",${getFunc || "NULL"},${setFunc || "NULL"}),`);
|
||||
}
|
||||
jsStructFinalizer(classId, structName, onFinalize) {
|
||||
const args = [{ type: "JSRuntime *", name: "rt" }, { type: "JSValue", name: "val" }];
|
||||
const body = this.function(`js_${structName}_finalizer`, "void", args, true);
|
||||
|
@ -410,8 +423,9 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
cond.returnExp("JS_EXCEPTION");
|
||||
});
|
||||
fun.declare(field, type, false, "ptr->" + field);
|
||||
// TODO: to JS
|
||||
fun.jsToJs(type, "ret", field);
|
||||
fun.returnExp("ret");
|
||||
return fun;
|
||||
}
|
||||
}
|
||||
exports.GenericQuickJsGenerator = GenericQuickJsGenerator;
|
||||
|
@ -447,7 +461,7 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
// read parameters
|
||||
for (let i = 0; i < api.params.length; i++) {
|
||||
const para = api.params[i];
|
||||
fun.jsReadParameter(para.type, para.name, i);
|
||||
fun.jsToC(para.type, para.name, "argv[" + i + "]");
|
||||
}
|
||||
// call c function
|
||||
fun.call(api.name, api.params.map(x => x.name), api.returnType === "void" ? null : { type: api.returnType, name: "returnVal" });
|
||||
|
@ -460,8 +474,8 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
fun.statement("return JS_UNDEFINED");
|
||||
}
|
||||
else {
|
||||
// TODO: Convert to JS
|
||||
fun.statement("return retVal");
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal");
|
||||
fun.returnExp("returnVal");
|
||||
}
|
||||
// add binding to function declaration
|
||||
this.moduleFunctionList.jsFuncDef(jName, api.argc, fun.getTag("_name"));
|
||||
|
@ -475,8 +489,22 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
addApiStruct(struct, destructor, options) {
|
||||
const classId = this.declarations.jsClassId(`js_${struct.name}_class_id`);
|
||||
const finalizer = this.structs.jsStructFinalizer(classId, struct.name, (gen, ptr) => destructor && gen.call(destructor.name, ["*" + ptr]));
|
||||
//TODO: declareGetterSetter()
|
||||
const propDeclarations = this.structs.createGenerator();
|
||||
if (options && options.properties) {
|
||||
for (const field of Object.keys(options.properties)) {
|
||||
const type = struct.fields.find(x => x.name === field)?.type;
|
||||
if (!type)
|
||||
throw new Error(`Struct ${struct.name} does not contain field ${field}`);
|
||||
const el = options.properties[field];
|
||||
let _get = undefined;
|
||||
let _set = undefined;
|
||||
if (el.get)
|
||||
_get = this.structs.jsStructGetter(struct.name, classId, field, type);
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), undefined);
|
||||
}
|
||||
}
|
||||
const classFuncList = this.structs.jsFunctionList(`js_${struct.name}_proto_funcs`);
|
||||
classFuncList.child(propDeclarations);
|
||||
classFuncList.jsPropStringDef("[Symbol.toStringTag]", "Image");
|
||||
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"));
|
||||
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]);
|
||||
|
@ -559,7 +587,7 @@ function main() {
|
|||
core_gen.addApiFunctionByName("EndDrawing");
|
||||
core_gen.writeTo("src/bindings/js_raylib_core.h");
|
||||
const texture_gen = new raylib_header_1.RayLibHeader("raylib_texture", apiDesc);
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage");
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage", { properties: { width: { get: true } } });
|
||||
texture_gen.writeTo("src/bindings/js_raylib_texture.h");
|
||||
}
|
||||
main();
|
||||
|
|
|
@ -23,7 +23,18 @@ static void js_Image_finalizer(JSRuntime * rt, JSValue val) {
|
|||
}
|
||||
}
|
||||
|
||||
static JSValue js_Image_get_width(JSContext* ctx, JSValueConst this_val) {
|
||||
Image* ptr = JS_GetOpaque2(ctx, this_val, js_Image_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int width = ptr->width;
|
||||
JSValue ret = JS_NewInt32(ctx, width);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_Image_proto_funcs[] = {
|
||||
JS_CGETSET_DEF("width",js_Image_get_width,NULL),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]","Image", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue