z3-z3-4.13.0.src.api.js.scripts.make-cc-wrapper.ts Maven / Gradle / Ivy
The newest version!
// generates c wrappers with off-thread versions of specified functions
import path from 'path';
import { asyncFuncs } from './async-fns';
import { functions } from './parse-api';
export function makeCCWrapper() {
let wrappers = [];
for (let fnName of asyncFuncs) {
let fn = functions.find(f => f.name === fnName);
if (fn == null) {
throw new Error(`could not find definition for ${fnName}`);
}
let wrapper;
if (fn.cRet === 'Z3_string') {
wrapper = `wrapper_str`;
} else if (['int', 'unsigned', 'void'].includes(fn.cRet) || fn.cRet.startsWith('Z3_')) {
wrapper = `wrapper`;
} else {
throw new Error(`async function with unknown return type ${fn.cRet}`);
}
wrappers.push(
`
extern "C" void async_${fn.name}(${fn.params
.map(p => `${p.isConst ? 'const ' : ''}${p.cType}${p.isPtr ? '*' : ''} ${p.name}${p.isArray ? '[]' : ''}`)
.join(', ')}) {
${wrapper}(${fn.params.map(p => `${p.name}`).join(', ')});
}
`.trim(),
);
}
return `// THIS FILE IS AUTOMATICALLY GENERATED BY ${path.basename(__filename)}
// DO NOT EDIT IT BY HAND
#include
#include
#include "../../z3.h"
template
void wrapper(Args&&... args) {
std::thread t([...args = std::forward(args)] {
try {
auto result = fn(args...);
MAIN_THREAD_ASYNC_EM_ASM({
resolve_async($0);
}, result);
} catch (std::exception& e) {
MAIN_THREAD_ASYNC_EM_ASM({
reject_async(new Error(UTF8ToString($0)));
}, e.what());
} catch (...) {
MAIN_THREAD_ASYNC_EM_ASM({
reject_async('failed with unknown exception');
});
}
});
t.detach();
}
template
void wrapper_str(Args&&... args) {
std::thread t([...args = std::forward(args)] {
try {
auto result = fn(args...);
MAIN_THREAD_ASYNC_EM_ASM({
resolve_async(UTF8ToString($0));
}, result);
} catch (std::exception& e) {
MAIN_THREAD_ASYNC_EM_ASM({
reject_async(new Error(UTF8ToString($0)));
}, e.what());
} catch (...) {
MAIN_THREAD_ASYNC_EM_ASM({
reject_async(new Error('failed with unknown exception'));
});
}
});
t.detach();
}
class Z3Exception : public std::exception {
public:
const std::string m_msg;
Z3Exception(const std::string& msg) : m_msg(msg) {}
virtual const char* what() const throw () {
return m_msg.c_str();
}
};
void throwy_error_handler(Z3_context ctx, Z3_error_code c) {
throw Z3Exception(Z3_get_error_msg(ctx, c));
}
void noop_error_handler(Z3_context ctx, Z3_error_code c) {
// pass
}
extern "C" void set_throwy_error_handler(Z3_context ctx) {
Z3_set_error_handler(ctx, throwy_error_handler);
}
extern "C" void set_noop_error_handler(Z3_context ctx) {
Z3_set_error_handler(ctx, noop_error_handler);
}
${wrappers.join('\n\n')}
`;
}
if (require.main === module) {
console.log(makeCCWrapper());
}