Skip to content

Commit 90ddc2d

Browse files
committed
Add enum support to QuickJS generator.
1 parent 11cc603 commit 90ddc2d

File tree

3 files changed

+148
-70
lines changed

3 files changed

+148
-70
lines changed

src/Generator/Generators/QuickJS/QuickJSMarshal.cs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,15 @@ public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals)
136136
return VisitPrimitiveType(builtin.Type);
137137
}
138138

139+
public override bool VisitEnumItemDecl(Enumeration.Item item)
140+
{
141+
var @enum = item.Namespace as Enumeration;
142+
return VisitPrimitiveType(@enum.BuiltinType.Type);
143+
}
144+
139145
public bool VisitPrimitiveType(PrimitiveType primitive)
140146
{
141-
var retName = Generator.GeneratedIdentifier(Context.ArgName);
147+
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
142148
Context.Before.Write($"JSValue {retName} = ");
143149

144150
switch (primitive)
@@ -341,10 +347,9 @@ public override bool VisitTypedefDecl(TypedefDecl typedef)
341347

342348
public override bool VisitEnumDecl(Enumeration @enum)
343349
{
344-
var typePrinter = new CppTypePrinter(Context.Context);
345-
typePrinter.PushContext(TypePrinterContextKind.Managed);
346-
var typeName = typePrinter.VisitDeclaration(@enum);
347-
Context.Return.Write($"({typeName}){Context.ReturnVarName}");
350+
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
351+
Context.Before.WriteLine($"JSValue {retName} = JS_NewInt32(ctx, (int32_t) {Context.ReturnVarName});");
352+
Context.Return.Write(retName);
348353

349354
return true;
350355
}
@@ -492,72 +497,82 @@ public bool VisitPrimitiveType(PrimitiveType primitive)
492497
var typePrinter = new CppTypePrinter(Context.Context);
493498
var type = typePrinter.VisitPrimitiveType(primitive);
494499

495-
Context.Before.WriteLine($"{type} {Context.ArgName};");
500+
var argName = Context.Parameter.Name;
501+
Context.Before.WriteLine($"{type} {argName};");
496502

497503
switch (primitive)
498504
{
499505
case PrimitiveType.Void:
500506
return true;
501507

502508
case PrimitiveType.Bool:
503-
Context.Before.WriteLine($"{Context.ArgName} = JS_ToBool(ctx, argv[{Context.ParameterIndex}]);");
504-
Context.Before.WriteLine($"if ({Context.ArgName} == -1)");
509+
Context.Before.WriteLine($"{argName} = JS_ToBool(ctx, argv[{Context.ParameterIndex}]);");
510+
Context.Before.WriteLine($"if ({argName} == -1)");
505511
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
512+
Context.Return.Write($"{argName}");
506513
return true;
507514

508515
case PrimitiveType.Char:
509516
case PrimitiveType.SChar:
510517
case PrimitiveType.UChar:
511-
Context.Before.WriteLine($"int32_t _{Context.ArgName};");
512-
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
518+
Context.Before.WriteLine($"int32_t _{argName};");
519+
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
513520
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
514-
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
521+
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
522+
Context.Return.Write($"{argName}");
515523
return true;
516524

517525
case PrimitiveType.Short:
518526
case PrimitiveType.UShort:
519-
Context.Before.WriteLine($"int32_t _{Context.ArgName};");
520-
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
527+
Context.Before.WriteLine($"int32_t _{argName};");
528+
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
521529
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
522-
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
530+
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
531+
Context.Return.Write($"{argName}");
523532
return true;
524533

525534
case PrimitiveType.Int:
526535
case PrimitiveType.Long:
527-
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
536+
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
528537
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
538+
Context.Return.Write($"{argName}");
529539
return true;
530540

531541
case PrimitiveType.UInt:
532542
case PrimitiveType.ULong:
533-
Context.Before.WriteLine($"if (JS_ToUint32(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
543+
Context.Before.WriteLine($"if (JS_ToUint32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
534544
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
545+
Context.Return.Write($"{argName}");
535546
return true;
536547

537548
case PrimitiveType.LongLong:
538-
Context.Before.WriteLine($"int64_t _{Context.ArgName};");
539-
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
549+
Context.Before.WriteLine($"int64_t _{argName};");
550+
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
540551
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
541-
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
552+
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
553+
Context.Return.Write($"{argName}");
542554
return true;
543555

544556
case PrimitiveType.ULongLong:
545-
Context.Before.WriteLine($"int64_t _{Context.ArgName};");
546-
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
557+
Context.Before.WriteLine($"int64_t _{argName};");
558+
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
547559
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
548-
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
560+
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
561+
Context.Return.Write($"{argName}");
549562
return true;
550563

551564
case PrimitiveType.Float:
552-
Context.Before.WriteLine($"double _{Context.ArgName};");
553-
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
565+
Context.Before.WriteLine($"double _{argName};");
566+
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
554567
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
555-
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
568+
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
569+
Context.Return.Write($"{argName}");
556570
return true;
557571

558572
case PrimitiveType.Double:
559-
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
573+
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
560574
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
575+
Context.Return.Write($"{argName}");
561576
return true;
562577

563578
case PrimitiveType.WideChar:
@@ -747,8 +762,11 @@ public override bool VisitTypedefDecl(TypedefDecl typedef)
747762

748763
public override bool VisitEnumDecl(Enumeration @enum)
749764
{
750-
Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName,
751-
Context.Parameter.Name);
765+
VisitPrimitiveType(@enum.BuiltinType.Type);
766+
767+
Context.Return.StringBuilder.Clear();
768+
Context.Return.Write($"(::{@enum.QualifiedOriginalName}){Context.Parameter.Name}");
769+
752770
return true;
753771
}
754772

src/Generator/Generators/QuickJS/QuickJSSources.cs

Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using CppSharp.AST.Extensions;
77
using CppSharp.Generators.C;
88
using static CppSharp.Generators.Cpp.NAPISources;
9+
using static CppSharp.Generators.Cpp.NAPIInvokes;
910

1011
namespace CppSharp.Generators.Cpp
1112
{
@@ -185,8 +186,26 @@ public override bool VisitEnumDecl(Enumeration @enum)
185186
PushBlock(BlockKind.Enum);
186187
{
187188
Write($"static void register_enum_{GetCIdentifier(Context, @enum)}");
188-
WriteLine("(JSContext *ctx, JSModuleDef *m)");
189+
WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)");
190+
WriteOpenBraceAndIndent();
191+
192+
WriteLine("if (!set)");
189193
WriteOpenBraceAndIndent();
194+
{
195+
WriteLine($"int status = JS_AddModuleExport(ctx, m, \"{@enum.Name}\");");
196+
WriteLine("assert(status != -1);");
197+
WriteLine("return;");
198+
}
199+
UnindentAndWriteCloseBrace();
200+
NewLine();
201+
202+
var sources = new QuickJSRegisterImpl(Context);
203+
sources.Indent(CurrentIndentation);
204+
@enum.Visit(sources);
205+
Write(sources.Generate());
206+
207+
WriteLine($"int status = JS_SetModuleExport(ctx, m, \"{@enum.Name}\", val);");
208+
WriteLine("assert(status != -1);");
190209

191210
UnindentAndWriteCloseBrace();
192211
}
@@ -196,69 +215,100 @@ public override bool VisitEnumDecl(Enumeration @enum)
196215
}
197216
}
198217

199-
public class QuickJSInvokes : NAPIInvokes
218+
public class QuickJSRegisterImpl : QuickJSInvokes
200219
{
201-
public QuickJSInvokes(BindingContext context)
220+
public QuickJSRegisterImpl(BindingContext context)
202221
: base(context, null)
203222
{
204223
}
205224

206-
public QuickJSInvokes(BindingContext context, IEnumerable<TranslationUnit> units)
207-
: base(context, units)
225+
public override bool VisitClassDecl(Class @class)
208226
{
227+
228+
return true;
209229
}
210230

211-
public override ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
212-
Function function = null)
231+
public override bool VisitMethodDecl(Method method)
213232
{
214-
var paramMarshal = new ParamMarshal { Name = param.Name, Param = param };
233+
if (method.IsConstructor)
234+
return true;
235+
236+
PushBlock(BlockKind.Method);
237+
{
238+
}
239+
PopBlock(NewLineKind.BeforeNextBlock);
215240

216-
var argName = Generator.GeneratedIdentifier(param.Name);
241+
return true;
242+
}
217243

218-
Parameter effectiveParam = param;
219-
var isRef = param.IsOut || param.IsInOut;
220-
var paramType = param.Type;
244+
public override bool VisitEnumDecl(Enumeration @enum)
245+
{
246+
WriteLine("JSValue val = JS_NewObject(ctx);");
247+
NewLine();
221248

222-
var ctx = new MarshalContext(Context, CurrentIndentation)
249+
PushBlock();
223250
{
224-
Parameter = effectiveParam,
225-
ParameterIndex = paramIndex,
226-
ArgName = argName,
227-
Function = function
228-
};
251+
foreach (var item in @enum.Items)
252+
item.Visit(this);
253+
}
254+
PopBlock(NewLineKind.Always);
229255

230-
var marshal = new QuickJSMarshalManagedToNativePrinter(ctx);
231-
effectiveParam.Visit(marshal);
256+
return true;
257+
}
232258

233-
if (string.IsNullOrEmpty(marshal.Context.Before))
234-
throw new Exception($"Cannot marshal argument of function '{function.QualifiedOriginalName}'");
259+
public override bool VisitEnumItemDecl(Enumeration.Item item)
260+
{
261+
PushBlock(BlockKind.EnumItem);
262+
{
263+
WriteLine("// " + item.Name);
264+
WriteOpenBraceAndIndent();
265+
{
266+
var ctx = new MarshalContext(Context, CurrentIndentation)
267+
{
268+
ArgName = item.Value.ToString(),
269+
ReturnVarName = "item"
270+
};
235271

236-
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
237-
Write(marshal.Context.Before);
272+
var marshal = GetMarshalNativeToManagedPrinter(ctx);
273+
item.Visit(marshal);
238274

239-
NewLine();
275+
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
276+
Write(marshal.Context.Before);
240277

241-
paramMarshal.Name = argName;
242-
return paramMarshal;
278+
WriteLine($"JS_SetPropertyStr(ctx, val, \"{item.Name}\", {marshal.Context.Return});");
279+
}
280+
UnindentAndWriteCloseBrace();
281+
}
282+
PopBlock(NewLineKind.BeforeNextBlock);
283+
return true;
243284
}
244285

245-
public override void GenerateFunctionCallReturnMarshal(Function function)
286+
public override bool VisitProperty(Property property)
246287
{
247-
var ctx = new MarshalContext(Context, CurrentIndentation)
248-
{
249-
ArgName = Helpers.ReturnIdentifier,
250-
ReturnVarName = Helpers.ReturnIdentifier,
251-
ReturnType = function.ReturnType
252-
};
288+
return true;
289+
}
290+
}
253291

254-
var marshal = new QuickJSMarshalNativeToManagedPrinter(ctx);
255-
function.ReturnType.Visit(marshal);
292+
public class QuickJSInvokes : NAPIInvokes
293+
{
294+
public QuickJSInvokes(BindingContext context)
295+
: base(context, null)
296+
{
297+
}
256298

257-
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
258-
Write(marshal.Context.Before);
299+
public QuickJSInvokes(BindingContext context, IEnumerable<TranslationUnit> units)
300+
: base(context, units)
301+
{
302+
}
259303

260-
NewLine();
261-
WriteLine($"return {marshal.Context.Return};");
304+
public override MarshalPrinter<MarshalContext> GetMarshalManagedToNativePrinter(MarshalContext ctx)
305+
{
306+
return new QuickJSMarshalManagedToNativePrinter(ctx);
307+
}
308+
309+
public override MarshalPrinter<MarshalContext> GetMarshalNativeToManagedPrinter(MarshalContext ctx)
310+
{
311+
return new QuickJSMarshalNativeToManagedPrinter(ctx);
262312
}
263313

264314
public override void GenerateFunctionGroup(List<Function> @group)
@@ -278,8 +328,7 @@ public override void GenerateFunctionCallback(List<Function> @group)
278328
var callbackId = $"callback_{type}_{GetCIdentifier(Context, function)}";
279329

280330
PushBlock();
281-
Write("extern \"C\" ");
282-
WriteLine($"JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,");
331+
WriteLine($"static JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,");
283332
WriteLineIndent("int argc, JSValueConst* argv)");
284333
WriteOpenBraceAndIndent();
285334

tests2/quickjs/test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,15 @@ function builtins()
9393
eq(test.PassAndReturnsUInt64(uint64.max), uint64.max);
9494
}
9595

96+
function enums()
97+
{
98+
eq(test.Enum0.Item0, 0);
99+
eq(test.Enum0.Item1, 1);
100+
eq(test.Enum0.Item2, 5);
101+
102+
eq(test.ReturnsEnum(), test.Enum0.Item0);
103+
eq(test.PassAndReturnsEnum(test.Enum0.Item1), test.Enum0.Item1);
104+
}
105+
96106
builtins();
107+
enums();

0 commit comments

Comments
 (0)