|
|
@ -5,6 +5,7 @@ using System.Linq; |
|
|
|
using CppSharp.AST; |
|
|
|
using CppSharp.AST; |
|
|
|
using CppSharp.AST.Extensions; |
|
|
|
using CppSharp.AST.Extensions; |
|
|
|
using CppSharp.Generators.C; |
|
|
|
using CppSharp.Generators.C; |
|
|
|
|
|
|
|
using static CppSharp.Generators.Cpp.NAPISources; |
|
|
|
|
|
|
|
|
|
|
|
namespace CppSharp.Generators.Cpp |
|
|
|
namespace CppSharp.Generators.Cpp |
|
|
|
{ |
|
|
|
{ |
|
|
@ -12,7 +13,7 @@ namespace CppSharp.Generators.Cpp |
|
|
|
/// Generates QuickJS C/C++ source files.
|
|
|
|
/// Generates QuickJS C/C++ source files.
|
|
|
|
/// QuickJS documentation: https://bellard.org/quickjs/
|
|
|
|
/// QuickJS documentation: https://bellard.org/quickjs/
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public class QuickJSSources : NAPICallbacks |
|
|
|
public class QuickJSSources : NAPISources |
|
|
|
{ |
|
|
|
{ |
|
|
|
public QuickJSSources(BindingContext context, IEnumerable<TranslationUnit> units) |
|
|
|
public QuickJSSources(BindingContext context, IEnumerable<TranslationUnit> units) |
|
|
|
: base(context, units) |
|
|
|
: base(context, units) |
|
|
@ -24,32 +25,193 @@ namespace CppSharp.Generators.Cpp |
|
|
|
GenerateFilePreamble(CommentKind.BCPL); |
|
|
|
GenerateFilePreamble(CommentKind.BCPL); |
|
|
|
|
|
|
|
|
|
|
|
PushBlock(BlockKind.Includes); |
|
|
|
PushBlock(BlockKind.Includes); |
|
|
|
|
|
|
|
|
|
|
|
WriteInclude(new CInclude() |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
File = "quickjs.h", |
|
|
|
WriteInclude("quickjs.h", CInclude.IncludeKind.Angled); |
|
|
|
Kind = CInclude.IncludeKind.Angled |
|
|
|
WriteInclude("assert.h", CInclude.IncludeKind.Angled); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var unit in TranslationUnits) |
|
|
|
foreach (var unit in TranslationUnits) |
|
|
|
{ |
|
|
|
{ |
|
|
|
WriteInclude(new CInclude() |
|
|
|
WriteInclude(unit.IncludePath, CInclude.IncludeKind.Angled); |
|
|
|
{ |
|
|
|
|
|
|
|
File = unit.IncludePath, |
|
|
|
|
|
|
|
Kind = CInclude.IncludeKind.Angled |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
NewLine(); |
|
|
|
NewLine(); |
|
|
|
|
|
|
|
} |
|
|
|
PopBlock(); |
|
|
|
PopBlock(); |
|
|
|
|
|
|
|
|
|
|
|
VisitNamespace(TranslationUnit); |
|
|
|
WriteLine("extern \"C\" {"); |
|
|
|
|
|
|
|
NewLine(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var registerGen = new QuickJSRegister(Context, TranslationUnits); |
|
|
|
|
|
|
|
registerGen.Process(); |
|
|
|
|
|
|
|
WriteLine(registerGen.Generate()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var name = GetTranslationUnitName(TranslationUnit); |
|
|
|
|
|
|
|
WriteLine($"void register_{name}(JSContext *ctx, JSModuleDef *m, bool set)"); |
|
|
|
|
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TranslationUnit.Visit(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UnindentAndWriteCloseBrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WriteLine("}"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitClassDecl(Class @class) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (@class.IsIncomplete) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(); |
|
|
|
|
|
|
|
WriteLine($"register_class_{GetCIdentifier(Context, @class)}(ctx, m, set);"); |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitFunctionDecl(Function function) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (function.IsOperator) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(); |
|
|
|
|
|
|
|
WriteLine($"register_function_{GetCIdentifier(Context, function)}(ctx, m, set);"); |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitEnumDecl(Enumeration @enum) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (@enum.IsIncomplete) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(); |
|
|
|
|
|
|
|
WriteLine($"register_enum_{GetCIdentifier(Context, @enum)}(ctx, m, set);"); |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class QuickJSRegister : NAPIRegister |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public QuickJSRegister(BindingContext context, IEnumerable<TranslationUnit> units) |
|
|
|
|
|
|
|
: base(context, units) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitClassDecl(Class @class) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (@class.IsIncomplete) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
PushBlock(BlockKind.InternalsClass, @class); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var callbacks = new QuickJSInvokes(Context); |
|
|
|
|
|
|
|
@class.Visit(callbacks); |
|
|
|
|
|
|
|
Write(callbacks.Generate()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(BlockKind.Class, @class); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Write($"static void register_class_{GetCIdentifier(Context, @class)}"); |
|
|
|
|
|
|
|
WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)"); |
|
|
|
|
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
var sources = new NAPIRegisterImpl(Context); |
|
|
|
|
|
|
|
sources.Indent(CurrentIndentation); |
|
|
|
|
|
|
|
@class.Visit(sources); |
|
|
|
|
|
|
|
Write(sources.Generate()); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UnindentAndWriteCloseBrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override void GenerateFunctionGroup(List<Function> group) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var function = group.First(); |
|
|
|
|
|
|
|
if (function.IsOperator) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(BlockKind.Function); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var callbacks = new QuickJSInvokes(Context); |
|
|
|
|
|
|
|
callbacks.GenerateFunctionGroup(group); |
|
|
|
|
|
|
|
Write(callbacks.Generate()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(BlockKind.Function); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Write($"static void register_function_{GetCIdentifier(Context, function)}"); |
|
|
|
|
|
|
|
WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)"); |
|
|
|
|
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WriteLine("if (!set)"); |
|
|
|
|
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
WriteLine($"int status = JS_AddModuleExport(ctx, m, \"{function.Name}\");"); |
|
|
|
|
|
|
|
WriteLine("assert(status != -1);"); |
|
|
|
|
|
|
|
WriteLine("return;"); |
|
|
|
|
|
|
|
UnindentAndWriteCloseBrace(); |
|
|
|
|
|
|
|
NewLine(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var callbackId = $"callback_function_{GetCIdentifier(Context, function)}"; |
|
|
|
|
|
|
|
var maxParams = @group.Max(f => f.Parameters.Count); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WriteLine($"JSValue val = JS_NewCFunction(ctx, {callbackId}, \"{function.Name}\"," + |
|
|
|
|
|
|
|
$" {maxParams});"); |
|
|
|
|
|
|
|
WriteLine($"int status = JS_SetModuleExport(ctx, m, \"{function.Name}\", val);"); |
|
|
|
|
|
|
|
WriteLine("assert(status != -1);"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UnindentAndWriteCloseBrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool VisitEnumDecl(Enumeration @enum) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (@enum.IsIncomplete) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PushBlock(BlockKind.Enum); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Write($"static void register_enum_{GetCIdentifier(Context, @enum)}"); |
|
|
|
|
|
|
|
WriteLine("(JSContext *ctx, JSModuleDef *m)"); |
|
|
|
|
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UnindentAndWriteCloseBrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
PopBlock(NewLineKind.BeforeNextBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class QuickJSInvokes : NAPIInvokes |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public QuickJSInvokes(BindingContext context) |
|
|
|
|
|
|
|
: base(context, null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public QuickJSInvokes(BindingContext context, IEnumerable<TranslationUnit> units) |
|
|
|
|
|
|
|
: base(context, units) |
|
|
|
|
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public override NAPICallbacks.ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, |
|
|
|
public override ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, |
|
|
|
Function function = null) |
|
|
|
Function function = null) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var paramMarshal = new NAPICallbacks.ParamMarshal { Name = param.Name, Param = param }; |
|
|
|
var paramMarshal = new ParamMarshal { Name = param.Name, Param = param }; |
|
|
|
|
|
|
|
|
|
|
|
var argName = Generator.GeneratedIdentifier(param.Name); |
|
|
|
var argName = Generator.GeneratedIdentifier(param.Name); |
|
|
|
|
|
|
|
|
|
|
@ -112,9 +274,12 @@ namespace CppSharp.Generators.Cpp |
|
|
|
{ |
|
|
|
{ |
|
|
|
var function = @group.First(); |
|
|
|
var function = @group.First(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var type = function is Method ? "method" : "function"; |
|
|
|
|
|
|
|
var callbackId = $"callback_{type}_{GetCIdentifier(Context, function)}"; |
|
|
|
|
|
|
|
|
|
|
|
PushBlock(); |
|
|
|
PushBlock(); |
|
|
|
Write("extern \"C\" "); |
|
|
|
Write("extern \"C\" "); |
|
|
|
WriteLine($"JSValue js_{function.Name}(JSContext* ctx, JSValueConst this_val,"); |
|
|
|
WriteLine($"JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,"); |
|
|
|
WriteLineIndent("int argc, JSValueConst* argv)"); |
|
|
|
WriteLineIndent("int argc, JSValueConst* argv)"); |
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
WriteOpenBraceAndIndent(); |
|
|
|
|
|
|
|
|
|
|
|