This commit is contained in:
parent
4018ff0fb9
commit
3365e5932a
@ -1,4 +1,4 @@
|
||||
// Get Custom Data
|
||||
// Get Custom Wrapper From Object
|
||||
template <typename Data>
|
||||
Data *custom_get(typename Data::__Self *self) {
|
||||
return (Data *) (self + 1);
|
||||
@ -86,6 +86,7 @@ protected:
|
||||
void __set_vtable() {
|
||||
static __VTable *vtable = nullptr;
|
||||
if (!vtable) {
|
||||
// Create VTable
|
||||
vtable = __dup_vtable(__VTable::base);
|
||||
__patch_vtable(vtable);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ export const STRUCTURE_FILES: Record<string, string> = {};
|
||||
export const COMMENT = '//';
|
||||
export const INTERNAL = '__';
|
||||
export const BUILDING_SYMBOLS_GUARD = 'BUILDING_SYMBOLS_LIB';
|
||||
export const CONSTRUCTOR_FUNCTION_NAME = 'constructor';
|
||||
export const SELF_ARG = 'self';
|
||||
// Read Definition File
|
||||
export function readDefinition(name: string) {
|
||||
|
110
src/custom.ts
110
src/custom.ts
@ -1,4 +1,5 @@
|
||||
import { CONSTRUCTOR_FUNCTION_NAME, formatType, forwardArguments, INDENT, INTERNAL, SELF_ARG } from './common';
|
||||
import { formatType, forwardArguments, INDENT, INTERNAL, SELF_ARG } from './common';
|
||||
import { Method } from './method';
|
||||
import { Struct } from './struct';
|
||||
import { structuresWithVTableAddress } from './vtable';
|
||||
|
||||
@ -15,9 +16,8 @@ export class CustomWrapperGenerator {
|
||||
#getBase() {
|
||||
return `${INTERNAL}CustomBase<${this.#struct.name}, ${this.#struct.getVTable().getName()}>`;
|
||||
}
|
||||
#getMethods() {
|
||||
#getVirtualMethods() {
|
||||
const out = [];
|
||||
out.push(this.#struct.getMainConstructor());
|
||||
const methods = this.#struct.getVTable().getMethods(false);
|
||||
for (const method of methods) {
|
||||
if (method) {
|
||||
@ -30,6 +30,55 @@ export class CustomWrapperGenerator {
|
||||
return 'Custom' + this.#struct.name;
|
||||
}
|
||||
|
||||
// Generate Methods
|
||||
#generateMethods(methods: Method[], isConstructor: boolean) {
|
||||
let out = '';
|
||||
for (const method of methods) {
|
||||
// Generate Method Signature
|
||||
out += INDENT;
|
||||
if (isConstructor) {
|
||||
out += 'explicit ' + this.#getName();
|
||||
} else {
|
||||
out += 'virtual ' + formatType(method.returnType) + method.shortName;
|
||||
}
|
||||
out += method.getArgs(false) + ';\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#generateMethodsCode(methods: Method[], isConstructor: boolean) {
|
||||
let out = '';
|
||||
for (const method of methods) {
|
||||
const name = method.shortName;
|
||||
// Generate Method Signature
|
||||
if (!isConstructor) {
|
||||
out += formatType(method.returnType);
|
||||
}
|
||||
out += this.#getName() + '::';
|
||||
out += isConstructor ? this.#getName() : name;
|
||||
const args = method.getArgs(false);
|
||||
out += args + ' {\n';
|
||||
// Generate Method Code
|
||||
out += INDENT;
|
||||
if (!isConstructor) {
|
||||
// Virtual Method
|
||||
if (method.doesReturnValue()) {
|
||||
out += 'return ';
|
||||
}
|
||||
out += `${INTERNAL}VTable::base->${name}`;
|
||||
} else {
|
||||
// Constructor
|
||||
out += method.getDirectCall();
|
||||
}
|
||||
out += forwardArguments(args, ['this->self']) + ';\n';
|
||||
if (isConstructor) {
|
||||
// Setup VTable
|
||||
out += `${INDENT}${INTERNAL}set_vtable();\n`;
|
||||
}
|
||||
out += '}\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Generate Header
|
||||
generate() {
|
||||
let out = '';
|
||||
@ -40,26 +89,15 @@ export class CustomWrapperGenerator {
|
||||
}
|
||||
|
||||
// Structure
|
||||
const base = this.#getBase();
|
||||
out += `struct ${this.#getName()} : ${base} {\n`;
|
||||
out += `struct ${this.#getName()} : ${this.#getBase()} {\n`;
|
||||
|
||||
// Methods
|
||||
const methods = this.#getMethods();
|
||||
for (const method of methods) {
|
||||
// Generate Method
|
||||
const name = method.shortName;
|
||||
out += INDENT;
|
||||
if (name === CONSTRUCTOR_FUNCTION_NAME) {
|
||||
out += 'explicit ' + this.#getName();
|
||||
} else {
|
||||
out += 'virtual ' + formatType(method.returnType) + name;
|
||||
}
|
||||
out += method.getArgs(false) + ';\n';
|
||||
}
|
||||
out += this.#generateMethods(this.#struct.getConstructors(), true);
|
||||
out += this.#generateMethods(this.#getVirtualMethods(), false);
|
||||
|
||||
// VTable
|
||||
out += 'private:\n';
|
||||
out += INDENT + `virtual void ${INTERNAL}patch_vtable(${base}::${INTERNAL}VTable *) override;\n`;
|
||||
out += INDENT + `void ${INTERNAL}patch_vtable(${INTERNAL}VTable *) override;\n`;
|
||||
out += '};\n';
|
||||
|
||||
// Return
|
||||
@ -71,36 +109,9 @@ export class CustomWrapperGenerator {
|
||||
let out = '';
|
||||
|
||||
// Methods
|
||||
const methods = this.#getMethods();
|
||||
for (const method of methods) {
|
||||
const name = method.shortName;
|
||||
const isConstructor = name === CONSTRUCTOR_FUNCTION_NAME;
|
||||
// Generate Method
|
||||
if (!isConstructor) {
|
||||
out += formatType(method.returnType);
|
||||
}
|
||||
out += this.#getName() + '::';
|
||||
out += isConstructor ? this.#getName() : name;
|
||||
const args = method.getArgs(false);
|
||||
out += args + ' {\n';
|
||||
out += INDENT;
|
||||
const forwardedArgs = forwardArguments(args, ['this->self']);
|
||||
if (!isConstructor) {
|
||||
// Virtual Method
|
||||
if (method.doesReturnValue()) {
|
||||
out += 'return ';
|
||||
}
|
||||
out += `${INTERNAL}VTable::base->${name}${forwardedArgs}`;
|
||||
} else {
|
||||
// Constructor
|
||||
out += method.getDirectCall() + forwardedArgs;
|
||||
}
|
||||
out += ';\n';
|
||||
if (isConstructor) {
|
||||
out += `${INDENT}${INTERNAL}set_vtable();\n`;
|
||||
}
|
||||
out += '}\n';
|
||||
}
|
||||
out += this.#generateMethodsCode(this.#struct.getConstructors(), true);
|
||||
const methods = this.#getVirtualMethods();
|
||||
out += this.#generateMethodsCode(methods, false);
|
||||
|
||||
// VTable
|
||||
const base = this.#getBase();
|
||||
@ -108,9 +119,6 @@ export class CustomWrapperGenerator {
|
||||
out += `${INDENT}${base}::${INTERNAL}patch_vtable(vtable);\n`;
|
||||
for (const method of methods) {
|
||||
const name = method.shortName;
|
||||
if (name === CONSTRUCTOR_FUNCTION_NAME) {
|
||||
continue;
|
||||
}
|
||||
// Patch Entry
|
||||
out += `${INDENT}vtable->${name} = []${method.getArgs()} {\n`;
|
||||
out += INDENT + INDENT;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { COMMENT, CONSTRUCTOR_FUNCTION_NAME, extendErrorMessage, EXTENSION, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
||||
import { COMMENT, extendErrorMessage, EXTENSION, parseTypeAndName, readDefinition, safeParseInt, syntaxError } from './common';
|
||||
import { Method } from './method';
|
||||
import { Property, StaticProperty } from './property';
|
||||
import { Struct } from './struct';
|
||||
@ -146,27 +146,27 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
||||
case 'method': {
|
||||
// Add Method
|
||||
const method = parseMethod(args, name, true, isExtended);
|
||||
target.addMethod(method, false);
|
||||
target.addMethod(method, false, false);
|
||||
break;
|
||||
}
|
||||
case 'virtual-method': {
|
||||
// Add Virtual Method
|
||||
const method = parseMethod(args, target.name, true, isExtended);
|
||||
target.addMethod(method, true);
|
||||
target.addMethod(method, true, false);
|
||||
break;
|
||||
}
|
||||
case 'static-method': {
|
||||
// Add Static Method
|
||||
if (!isExtended) {
|
||||
const method = parseMethod(args, target.name, false, false);
|
||||
target.addMethod(method, false);
|
||||
target.addMethod(method, false, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'constructor': {
|
||||
// Constructor
|
||||
if (!isExtended) {
|
||||
let data = target.name + ' *' + CONSTRUCTOR_FUNCTION_NAME;
|
||||
let data = target.name + ' *constructor';
|
||||
if (args.startsWith('(')) {
|
||||
// No Custom Name
|
||||
} else {
|
||||
@ -175,7 +175,7 @@ export function load(target: Struct, name: string, isExtended: boolean) {
|
||||
}
|
||||
data += args;
|
||||
const method = parseMethod(data, target.name, true, false);
|
||||
target.addMethod(method, false);
|
||||
target.addMethod(method, false, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { INDENT, STRUCTURE_FILES, toHex, assertSize, INTERNAL, preventConstruction, BUILDING_SYMBOLS_GUARD, formatType, forwardArguments, CONSTRUCTOR_FUNCTION_NAME } from './common';
|
||||
import { INDENT, STRUCTURE_FILES, toHex, assertSize, INTERNAL, preventConstruction, BUILDING_SYMBOLS_GUARD, formatType, forwardArguments } from './common';
|
||||
import { CustomWrapperGenerator } from './custom';
|
||||
import { Method } from './method';
|
||||
import { Property, StaticProperty } from './property';
|
||||
@ -9,6 +9,7 @@ export class Struct {
|
||||
readonly name: string;
|
||||
#vtable: VTable | null;
|
||||
readonly #methods: Method[];
|
||||
readonly #constructors: Method[];
|
||||
readonly #properties: Property[];
|
||||
#size: number | null;
|
||||
readonly #dependencies: string[];
|
||||
@ -21,6 +22,7 @@ export class Struct {
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
this.#methods = [];
|
||||
this.#constructors = [];
|
||||
this.#properties = [];
|
||||
this.#vtable = null;
|
||||
this.#size = null;
|
||||
@ -54,7 +56,7 @@ export class Struct {
|
||||
}
|
||||
|
||||
// Add Method
|
||||
addMethod(method: Method, isVirtual: boolean) {
|
||||
addMethod(method: Method, isVirtual: boolean, isConstructor: boolean) {
|
||||
if (method.returnType !== this.name && method.returnType in STRUCTURE_FILES) {
|
||||
this.#addDependency(method.returnType);
|
||||
}
|
||||
@ -66,6 +68,8 @@ export class Struct {
|
||||
} else {
|
||||
if (method.isInherited) {
|
||||
this.#addDependency(method.self);
|
||||
} else if (isConstructor) {
|
||||
this.#constructors.push(method);
|
||||
}
|
||||
this.#methods.push(method);
|
||||
}
|
||||
@ -106,13 +110,12 @@ export class Struct {
|
||||
this.getVTable();
|
||||
this.#custom = new CustomWrapperGenerator(this);
|
||||
}
|
||||
getMainConstructor() {
|
||||
for (const method of this.#methods) {
|
||||
if (method.shortName === CONSTRUCTOR_FUNCTION_NAME) {
|
||||
return method;
|
||||
getConstructors() {
|
||||
const out = this.#constructors;
|
||||
if (out.length === 0) {
|
||||
throw new Error('Custom Wrappers Require Constructors');
|
||||
}
|
||||
}
|
||||
throw new Error('Unable To Find Main Constructor');
|
||||
return out;
|
||||
}
|
||||
|
||||
// Generate Properties
|
||||
|
Loading…
x
Reference in New Issue
Block a user