Browse Source

Add enum support to QuickJS generator.

pull/1557/head
Joao Matos 4 years ago committed by João Matos
parent
commit
90ddc2dff5
  1. 74
      src/Generator/Generators/QuickJS/QuickJSMarshal.cs
  2. 133
      src/Generator/Generators/QuickJS/QuickJSSources.cs
  3. 11
      tests2/quickjs/test.js

74
src/Generator/Generators/QuickJS/QuickJSMarshal.cs

@ -136,9 +136,15 @@ namespace CppSharp.Generators.Cpp @@ -136,9 +136,15 @@ namespace CppSharp.Generators.Cpp
return VisitPrimitiveType(builtin.Type);
}
public override bool VisitEnumItemDecl(Enumeration.Item item)
{
var @enum = item.Namespace as Enumeration;
return VisitPrimitiveType(@enum.BuiltinType.Type);
}
public bool VisitPrimitiveType(PrimitiveType primitive)
{
var retName = Generator.GeneratedIdentifier(Context.ArgName);
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.Write($"JSValue {retName} = ");
switch (primitive)
@ -341,10 +347,9 @@ namespace CppSharp.Generators.Cpp @@ -341,10 +347,9 @@ namespace CppSharp.Generators.Cpp
public override bool VisitEnumDecl(Enumeration @enum)
{
var typePrinter = new CppTypePrinter(Context.Context);
typePrinter.PushContext(TypePrinterContextKind.Managed);
var typeName = typePrinter.VisitDeclaration(@enum);
Context.Return.Write($"({typeName}){Context.ReturnVarName}");
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.WriteLine($"JSValue {retName} = JS_NewInt32(ctx, (int32_t) {Context.ReturnVarName});");
Context.Return.Write(retName);
return true;
}
@ -492,7 +497,8 @@ namespace CppSharp.Generators.Cpp @@ -492,7 +497,8 @@ namespace CppSharp.Generators.Cpp
var typePrinter = new CppTypePrinter(Context.Context);
var type = typePrinter.VisitPrimitiveType(primitive);
Context.Before.WriteLine($"{type} {Context.ArgName};");
var argName = Context.Parameter.Name;
Context.Before.WriteLine($"{type} {argName};");
switch (primitive)
{
@ -500,64 +506,73 @@ namespace CppSharp.Generators.Cpp @@ -500,64 +506,73 @@ namespace CppSharp.Generators.Cpp
return true;
case PrimitiveType.Bool:
Context.Before.WriteLine($"{Context.ArgName} = JS_ToBool(ctx, argv[{Context.ParameterIndex}]);");
Context.Before.WriteLine($"if ({Context.ArgName} == -1)");
Context.Before.WriteLine($"{argName} = JS_ToBool(ctx, argv[{Context.ParameterIndex}]);");
Context.Before.WriteLine($"if ({argName} == -1)");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Char:
case PrimitiveType.SChar:
case PrimitiveType.UChar:
Context.Before.WriteLine($"int32_t _{Context.ArgName};");
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"int32_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Short:
case PrimitiveType.UShort:
Context.Before.WriteLine($"int32_t _{Context.ArgName};");
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"int32_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Int:
case PrimitiveType.Long:
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.UInt:
case PrimitiveType.ULong:
Context.Before.WriteLine($"if (JS_ToUint32(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"if (JS_ToUint32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.LongLong:
Context.Before.WriteLine($"int64_t _{Context.ArgName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"int64_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.ULongLong:
Context.Before.WriteLine($"int64_t _{Context.ArgName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"int64_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Float:
Context.Before.WriteLine($"double _{Context.ArgName};");
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &_{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"double _{argName};");
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{Context.ArgName} = ({type})_{Context.ArgName};");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Double:
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &{Context.ArgName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"if (JS_ToFloat64(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.WideChar:
@ -747,8 +762,11 @@ namespace CppSharp.Generators.Cpp @@ -747,8 +762,11 @@ namespace CppSharp.Generators.Cpp
public override bool VisitEnumDecl(Enumeration @enum)
{
Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName,
Context.Parameter.Name);
VisitPrimitiveType(@enum.BuiltinType.Type);
Context.Return.StringBuilder.Clear();
Context.Return.Write($"(::{@enum.QualifiedOriginalName}){Context.Parameter.Name}");
return true;
}

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

@ -6,6 +6,7 @@ using CppSharp.AST; @@ -6,6 +6,7 @@ using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators.C;
using static CppSharp.Generators.Cpp.NAPISources;
using static CppSharp.Generators.Cpp.NAPIInvokes;
namespace CppSharp.Generators.Cpp
{
@ -185,8 +186,26 @@ namespace CppSharp.Generators.Cpp @@ -185,8 +186,26 @@ namespace CppSharp.Generators.Cpp
PushBlock(BlockKind.Enum);
{
Write($"static void register_enum_{GetCIdentifier(Context, @enum)}");
WriteLine("(JSContext *ctx, JSModuleDef *m)");
WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)");
WriteOpenBraceAndIndent();
WriteLine("if (!set)");
WriteOpenBraceAndIndent();
{
WriteLine($"int status = JS_AddModuleExport(ctx, m, \"{@enum.Name}\");");
WriteLine("assert(status != -1);");
WriteLine("return;");
}
UnindentAndWriteCloseBrace();
NewLine();
var sources = new QuickJSRegisterImpl(Context);
sources.Indent(CurrentIndentation);
@enum.Visit(sources);
Write(sources.Generate());
WriteLine($"int status = JS_SetModuleExport(ctx, m, \"{@enum.Name}\", val);");
WriteLine("assert(status != -1);");
UnindentAndWriteCloseBrace();
}
@ -196,69 +215,100 @@ namespace CppSharp.Generators.Cpp @@ -196,69 +215,100 @@ namespace CppSharp.Generators.Cpp
}
}
public class QuickJSInvokes : NAPIInvokes
public class QuickJSRegisterImpl : QuickJSInvokes
{
public QuickJSInvokes(BindingContext context)
public QuickJSRegisterImpl(BindingContext context)
: base(context, null)
{
}
public QuickJSInvokes(BindingContext context, IEnumerable<TranslationUnit> units)
: base(context, units)
public override bool VisitClassDecl(Class @class)
{
return true;
}
public override ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex,
Function function = null)
public override bool VisitMethodDecl(Method method)
{
var paramMarshal = new ParamMarshal { Name = param.Name, Param = param };
if (method.IsConstructor)
return true;
PushBlock(BlockKind.Method);
{
}
PopBlock(NewLineKind.BeforeNextBlock);
var argName = Generator.GeneratedIdentifier(param.Name);
return true;
}
Parameter effectiveParam = param;
var isRef = param.IsOut || param.IsInOut;
var paramType = param.Type;
public override bool VisitEnumDecl(Enumeration @enum)
{
WriteLine("JSValue val = JS_NewObject(ctx);");
NewLine();
var ctx = new MarshalContext(Context, CurrentIndentation)
PushBlock();
{
Parameter = effectiveParam,
ParameterIndex = paramIndex,
ArgName = argName,
Function = function
};
foreach (var item in @enum.Items)
item.Visit(this);
}
PopBlock(NewLineKind.Always);
var marshal = new QuickJSMarshalManagedToNativePrinter(ctx);
effectiveParam.Visit(marshal);
return true;
}
if (string.IsNullOrEmpty(marshal.Context.Before))
throw new Exception($"Cannot marshal argument of function '{function.QualifiedOriginalName}'");
public override bool VisitEnumItemDecl(Enumeration.Item item)
{
PushBlock(BlockKind.EnumItem);
{
WriteLine("// " + item.Name);
WriteOpenBraceAndIndent();
{
var ctx = new MarshalContext(Context, CurrentIndentation)
{
ArgName = item.Value.ToString(),
ReturnVarName = "item"
};
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
Write(marshal.Context.Before);
var marshal = GetMarshalNativeToManagedPrinter(ctx);
item.Visit(marshal);
NewLine();
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
Write(marshal.Context.Before);
paramMarshal.Name = argName;
return paramMarshal;
WriteLine($"JS_SetPropertyStr(ctx, val, \"{item.Name}\", {marshal.Context.Return});");
}
UnindentAndWriteCloseBrace();
}
PopBlock(NewLineKind.BeforeNextBlock);
return true;
}
public override void GenerateFunctionCallReturnMarshal(Function function)
public override bool VisitProperty(Property property)
{
var ctx = new MarshalContext(Context, CurrentIndentation)
{
ArgName = Helpers.ReturnIdentifier,
ReturnVarName = Helpers.ReturnIdentifier,
ReturnType = function.ReturnType
};
return true;
}
}
var marshal = new QuickJSMarshalNativeToManagedPrinter(ctx);
function.ReturnType.Visit(marshal);
public class QuickJSInvokes : NAPIInvokes
{
public QuickJSInvokes(BindingContext context)
: base(context, null)
{
}
if (!string.IsNullOrWhiteSpace(marshal.Context.Before))
Write(marshal.Context.Before);
public QuickJSInvokes(BindingContext context, IEnumerable<TranslationUnit> units)
: base(context, units)
{
}
NewLine();
WriteLine($"return {marshal.Context.Return};");
public override MarshalPrinter<MarshalContext> GetMarshalManagedToNativePrinter(MarshalContext ctx)
{
return new QuickJSMarshalManagedToNativePrinter(ctx);
}
public override MarshalPrinter<MarshalContext> GetMarshalNativeToManagedPrinter(MarshalContext ctx)
{
return new QuickJSMarshalNativeToManagedPrinter(ctx);
}
public override void GenerateFunctionGroup(List<Function> @group)
@ -278,8 +328,7 @@ namespace CppSharp.Generators.Cpp @@ -278,8 +328,7 @@ namespace CppSharp.Generators.Cpp
var callbackId = $"callback_{type}_{GetCIdentifier(Context, function)}";
PushBlock();
Write("extern \"C\" ");
WriteLine($"JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,");
WriteLine($"static JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,");
WriteLineIndent("int argc, JSValueConst* argv)");
WriteOpenBraceAndIndent();

11
tests2/quickjs/test.js

@ -93,4 +93,15 @@ function builtins() @@ -93,4 +93,15 @@ function builtins()
eq(test.PassAndReturnsUInt64(uint64.max), uint64.max);
}
function enums()
{
eq(test.Enum0.Item0, 0);
eq(test.Enum0.Item1, 1);
eq(test.Enum0.Item2, 5);
eq(test.ReturnsEnum(), test.Enum0.Item0);
eq(test.PassAndReturnsEnum(test.Enum0.Item1), test.Enum0.Item1);
}
builtins();
enums();

Loading…
Cancel
Save