Browse Source

Add QuickJS runtime project and initial features.

pull/1581/head
Joao Matos 5 years ago committed by João Matos
parent
commit
91c65c5515
  1. 7
      src/Generator/Generators/QuickJS/QuickJSModule.cs
  2. 2
      src/Generator/Generators/QuickJS/QuickJSSources.cs
  3. 13
      src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.cpp
  4. 257
      src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h
  5. 202
      src/Generator/Generators/QuickJS/Runtime/Signal.cpp
  6. 24
      src/Generator/Generators/QuickJS/Runtime/Signal.h
  7. 2
      src/Generator/Generators/QuickJS/Runtime/premake5.lua

7
src/Generator/Generators/QuickJS/QuickJSModule.cs

@ -23,14 +23,11 @@ namespace CppSharp.Generators.Cpp
public override void Process() public override void Process()
{ {
GenerateFilePreamble(CommentKind.BCPL); GenerateFilePreamble(CommentKind.BCPL);
NewLine();
PushBlock(BlockKind.Includes); PushBlock(BlockKind.Includes);
{ {
WriteInclude(new CInclude() WriteInclude("CppSharp_QuickJS.h", CInclude.IncludeKind.Angled);
{
File = "quickjs.h",
Kind = CInclude.IncludeKind.Angled
});
foreach (var unit in TranslationUnits) foreach (var unit in TranslationUnits)
{ {

2
src/Generator/Generators/QuickJS/QuickJSSources.cs

@ -27,7 +27,7 @@ namespace CppSharp.Generators.Cpp
PushBlock(BlockKind.Includes); PushBlock(BlockKind.Includes);
{ {
WriteInclude("quickjs.h", CInclude.IncludeKind.Angled); WriteInclude("CppSharp_QuickJS.h", CInclude.IncludeKind.Angled);
WriteInclude("assert.h", CInclude.IncludeKind.Angled); WriteInclude("assert.h", CInclude.IncludeKind.Angled);
foreach (var unit in TranslationUnits) foreach (var unit in TranslationUnits)

13
src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.cpp

@ -0,0 +1,13 @@
#include "CppSharp_QuickJS.h"
extern "C"
{
extern void register_signal(JSContext *ctx, JSModuleDef *m, bool set, int phase);
void register_CppSharp_QuickJS(JSContext *ctx, JSModuleDef *m, bool set, int phase)
{
register_signal(ctx, m, set, phase);
}
} // extern "C"

257
src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h

@ -0,0 +1,257 @@
// ----------------------------------------------------------------------------
// <auto-generated>
// This is autogenerated code by CppSharp.
// Do not edit this file or all your changes will be lost after re-generation.
// </auto-generated>
// ----------------------------------------------------------------------------
extern "C"
{
#include <quickjs.h>
#include <cutils.h>
#if defined(__GNUC__) || defined(__clang__)
#define js_force_inline inline __attribute__((always_inline))
#else
#define js_force_inline inline
#endif
#define countof(x) (sizeof(x) / sizeof((x)[0]))
enum
{
__JS_ATOM_NULL = JS_ATOM_NULL,
#define DEF(name, str) JS_ATOM_ ## name,
#include <quickjs-atom.h>
#undef DEF
JS_ATOM_END,
};
struct JS_SignalContext
{
// TODO: List
JSValue function;
JSValue link;
JSContext *ctx;
};
typedef int JS_EventId;
typedef int JS_ClassId;
typedef DynBuf JS_EventMap;
struct JS_EventEntry
{
JS_EventId eventId;
JSValue value;
};
static JS_EventMap* JS_Interop_InitEventMap(JS_EventMap* map)
{
dbuf_init(map);
return map;
}
static void JS_Interop_FreeEventMap(JSContext* ctx, JS_EventMap* map)
{
JS_EventEntry* events = (JS_EventEntry*) map->buf;
int numEvents = (map->size / sizeof(JS_EventEntry));
for (int i = 0; i < numEvents; i++)
if (!JS_IsUndefined(events[i].value))
JS_FreeValue(ctx, events[i].value);
dbuf_free(map);
}
static int JS_Interop_BinarySearch(JS_EventEntry* arr, int l, int r, JS_EventId id)
{
if (r >= l) {
int mid = l + (r - l) / 2;
// If the element is present at the middle itself
if (arr[mid].eventId == id)
return mid;
// If element is smaller than mid, then it can only be present in left subarray
if (arr[mid].eventId > id)
return JS_Interop_BinarySearch(arr, l, mid - 1, id);
// Else the element can only be present in right subarray
return JS_Interop_BinarySearch(arr, mid + 1, r, id);
}
// We reach here when element is not present in array
return -1;
}
static JSValue JS_Interop_FindEvent(JS_EventMap* map, JS_EventId eventId)
{
JS_EventEntry* events = (JS_EventEntry*) map->buf;
int numEvents = (map->size / sizeof(JS_EventEntry));
if (numEvents == 0)
return JS_UNDEFINED;
int index = JS_Interop_BinarySearch(events, 0, numEvents, eventId);
return index >= 0 ? events[index].value : JS_UNDEFINED;
}
static int JS_Interop_InsertEvent(JS_EventMap* map, JS_EventId eventId,
JSValue value)
{
JS_EventEntry* events = (JS_EventEntry*) map->buf;
int numEvents = (map->size / sizeof(JS_EventEntry));
int index = 0;
for (int i = 0; i < numEvents; i++)
{
if (events[i].eventId == eventId) { index=-1; break; }
if (events[i].eventId > eventId) { index = i; break; }
index++;
}
if (index == -1)
return -1;
JS_EventEntry entry;
entry.eventId = eventId;
entry.value = value;
dbuf_write(map, index * sizeof(JS_EventEntry), (const uint8_t*) &entry,
sizeof(JS_EventEntry));
return 0;
}
static JSValue JS_Interop_InvokeConstructor(JSContext *ctx, JS_ClassId eventId,
JSValue argv[], int argc)
{
// TODO: Error handling.
JSValue proto = JS_GetClassProto(ctx, eventId);
JSValue ctor = JS_GetProperty(ctx, proto, JS_ATOM_constructor);
JSValue instance = JS_CallConstructor(ctx, ctor, argc, argv);
JS_FreeValue(ctx, ctor);
JS_FreeValue(ctx, proto);
return instance;
}
enum JS_Interop_InstanceKind
{
JS_INTEROP_INSTANCE_RAW_POINTER = 1,
JS_INTEROP_INSTANCE_SIGNAL_CONTEXT,
};
struct JS_Interop_ClassData
{
void* instance;
JSContext* ctx;
JS_EventMap events;
};
static JSValue JS_Interop_InitObject(JSContext *ctx, JSValue obj, JS_Interop_InstanceKind kind,
void* instance)
{
switch (kind)
{
case JS_INTEROP_INSTANCE_RAW_POINTER:
JS_SetOpaque(obj, instance);
return obj;
case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
JS_Interop_ClassData* data = (JS_Interop_ClassData*) js_mallocz(ctx, \
sizeof(JS_Interop_ClassData));
data->ctx = ctx;
data->instance = instance;
JS_Interop_InitEventMap(&data->events);
JS_SetOpaque(obj, data);
return obj;
}
return JS_UNDEFINED;
}
static JSValue JS_Interop_CleanupObject(JSValue obj, JS_Interop_InstanceKind kind)
{
switch (kind)
{
case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, 0);
JS_Interop_FreeEventMap(data->ctx, &data->events);
js_free(data->ctx, data);
}
return JS_UNDEFINED;
}
static void* JS_Interop_GetInstance(JSValue obj, JS_ClassId classId, JS_Interop_InstanceKind kind)
{
switch (kind)
{
case JS_INTEROP_INSTANCE_RAW_POINTER:
return JS_GetOpaque(obj, classId);
case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, classId);
return data != nullptr ? data->instance : nullptr;
}
return nullptr;
}
static JSValue JS_Interop_CreateFromInstance(JSContext* ctx, JS_ClassId classId,
JS_Interop_InstanceKind kind, void* instance)
{
if (instance == nullptr)
return JS_NULL;
// TODO: Error handling.
JSValue obj = JS_NewObjectClass(ctx, classId);
JS_Interop_InitObject(ctx, obj, kind, instance);
return obj;
}
static inline JS_BOOL JS_IsInt(JSValueConst v)
{
return JS_IsNumber(v);
}
static inline JS_BOOL JS_IsInt8(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsUInt8(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsInt16(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsUInt16(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsInt32(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsUInt32(JSValueConst v)
{
return JS_IsInt(v);
}
static inline JS_BOOL JS_IsFloat(JSValueConst v)
{
int tag = JS_VALUE_GET_TAG(v);
return JS_TAG_IS_FLOAT64(tag);
}
void register_CppSharp_QuickJS(JSContext *ctx, JSModuleDef *m, bool set, int phase);
#undef js_force_inline
} // extern "C"

202
src/Generator/Generators/QuickJS/Runtime/Signal.cpp

@ -0,0 +1,202 @@
// ----------------------------------------------------------------------------
// <auto-generated>
// This is autogenerated code by CppSharp.
// Do not edit this file or all your changes will be lost after re-generation.
// </auto-generated>
// ----------------------------------------------------------------------------
#include <CppSharp_QuickJS.h>
#include <assert.h>
extern "C" {
JSClassID classId__Signal;
// Signal::Signal
static JSValue callback_method_Signal_Signal(JSContext* ctx, JSValueConst this_val,
int argc, JSValueConst* argv)
{
// if (argc != 1)
// {
// return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
// }
wrap:
JSValue proto;
if (JS_IsUndefined(this_val))
proto = JS_GetClassProto(ctx, classId__Signal);
else
proto = JS_GetPropertyStr(ctx, this_val, "prototype");
if (JS_IsException(proto))
return proto;
JSValue __obj = JS_NewObjectProtoClass(ctx, proto, classId__Signal);
JS_FreeValue(ctx, proto);
JS_SignalContext* signalCtx = new JS_SignalContext;
signalCtx->ctx = ctx;
signalCtx->function = JS_UNDEFINED;
signalCtx->link = JS_UNDEFINED;
if (argc >= 1)
{
JSValue link = argv[0];
assert(JS_IsObject(link));
//JS_FreeValue(ctx, link);
signalCtx->link = link;
}
JS_SetOpaque(__obj, signalCtx);
return __obj;
}
// Signal::connect
static JSValue callback_method_Signal_connect(JSContext* ctx, JSValueConst this_val,
int argc, JSValueConst* argv)
{
if (argc < 1 || argc > 1)
{
return JS_ThrowRangeError(ctx, "Expected one argument of function type");
}
// Signal* instance = (Signal*) JS_GetOpaque(this_val, classId__Signal);
if (!JS_IsFunction(ctx, argv[0]))
return JS_ThrowTypeError(ctx, "Unsupported argument type");
// Connect logic
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
if (signalCtx == nullptr)
return JS_ThrowTypeError(ctx, "Could not find signal context");
assert(JS_IsObject(signalCtx->link));
if (!JS_IsUndefined(signalCtx->function))
return JS_ThrowRangeError(ctx, "Signal already contains a connected function");
signalCtx->function = JS_DupValue(ctx, argv[0]);
JSValue ____ret = JS_NewInt32(ctx, 0);
return ____ret;
}
// Signal::disconnect
static JSValue callback_method_Signal_disconnect(JSContext* ctx, JSValueConst this_val,
int argc, JSValueConst* argv)
{
if (argc < 1 || argc > 1)
{
return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
}
// Signal* instance = (Signal*) JS_GetOpaque(this_val, classId__Signal);
if (JS_IsNumber(argv[0]))
goto overload0;
goto error;
error:
return JS_ThrowTypeError(ctx, "Unsupported argument type");
// bool disconnect(Slot slot) { return 0; }
overload0:
{
int slot;
if (JS_ToInt32(ctx, (int32_t*) &slot, argv[0]))
return JS_EXCEPTION;
// auto __arg0 = (::Slot)slot;
// bool __ret = instance->disconnect(__arg0);
JSValue ____ret = JS_NewBool(ctx, 0);
return ____ret;
}
}
// Signal::isEmpty
static JSValue callback_method_Signal_isEmpty(JSContext* ctx, JSValueConst this_val,
int argc, JSValueConst* argv)
{
if (argc > 0)
{
return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
}
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
JSValue ____ret = JS_NewBool(ctx, JS_IsUndefined(signalCtx->function));
return ____ret;
}
static JSValue callback_class__Signal_toString(JSContext* ctx, JSValueConst this_val,
int argc, JSValueConst* argv)
{
return JS_NewString(ctx, "Signal");
}
void finalizer__Signal(JSRuntime *rt, JSValue val)
{
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(val, classId__Signal);
if (signalCtx == nullptr)
return;
if (!JS_IsUndefined(signalCtx->function))
return JS_FreeValue(signalCtx->ctx, signalCtx->function);
delete signalCtx;
JS_SetOpaque(val, nullptr);
}
static JSClassDef classDef__Signal
{
"Signal",
.finalizer = finalizer__Signal
};
static JSCFunctionListEntry funcDef__Signal[]
{
JS_CFUNC_DEF("connect", 1, callback_method_Signal_connect),
JS_CFUNC_DEF("disconnect", 1, callback_method_Signal_disconnect),
JS_CFUNC_DEF("isEmpty", 0, callback_method_Signal_isEmpty),
JS_CFUNC_DEF("toString", 0, callback_class__Signal_toString),
};
static void register_class__Signal(JSContext *ctx, JSModuleDef *m, bool set, int phase)
{
if (!set)
{
JS_AddModuleExport(ctx, m, "Signal");
return;
}
if (phase == 0)
{
JS_NewClassID(&classId__Signal);
JS_NewClass(JS_GetRuntime(ctx), classId__Signal, &classDef__Signal);
JSValue proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, proto, funcDef__Signal, sizeof(funcDef__Signal) / sizeof(funcDef__Signal[0]));
JS_SetClassProto(ctx, classId__Signal, proto);
JSValue ctor = JS_NewCFunction2(ctx, callback_method_Signal_Signal, "Signal", 1, JS_CFUNC_constructor, 0);
JS_SetConstructor(ctx, ctor, proto);
JS_SetModuleExport(ctx, m, "Signal", ctor);
}
}
void register_signal(JSContext *ctx, JSModuleDef *m, bool set, int phase)
{
register_class__Signal(ctx, m, set, phase);
}
} // extern "C"

24
src/Generator/Generators/QuickJS/Runtime/Signal.h

@ -0,0 +1,24 @@
// ----------------------------------------------------------------------------
// <auto-generated>
// This is autogenerated code by CppSharp.
// Do not edit this file or all your changes will be lost after re-generation.
// </auto-generated>
// ----------------------------------------------------------------------------
#pragma once
#include <quickjs.h>
class Signal
{
public:
Signal();
~Signal();
int connect(void (*function)());
bool disconnect(int slot);
bool isEmpty();
};

2
src/Generator/Generators/QuickJS/Runtime/premake5.lua

@ -0,0 +1,2 @@
project "cppsharp-quickjs-runtime"
files { "" }
Loading…
Cancel
Save