Skip to content

Commit eda9472

Browse files
committed
Реализован проброс процесса в конвертер
1 parent f69d97e commit eda9472

File tree

3 files changed

+62
-52
lines changed

3 files changed

+62
-52
lines changed

src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ public class ContextMethodsMapper<TInstance>
2626

2727
private readonly object _locker = new object();
2828

29-
private static readonly MethodInfo _genConvertParamMethod =
30-
typeof(InternalMethInfo).GetMethod("ConvertParam",
31-
BindingFlags.Static | BindingFlags.NonPublic);
32-
33-
private static readonly MethodInfo _genConvertReturnMethod =
34-
typeof(InternalMethInfo).GetMethod("ConvertReturnValue",
35-
BindingFlags.Static | BindingFlags.NonPublic);
36-
3729
private void Init()
3830
{
3931
if (_methodPtrs == null)
@@ -177,7 +169,7 @@ private static ContextCallableDelegate<TInstance> CreateFunction(ContextMethodIn
177169
{
178170
var methodCall = MethodCallExpression(target, out var instParam, out var argsParam, out var processParam);
179171

180-
var convertRetMethod = _genConvertReturnMethod.MakeGenericMethod(target.ReturnType);
172+
var convertRetMethod = ContextValuesMarshaller.BslReturnValueGenericConverter.MakeGenericMethod(target.ReturnType);
181173
var convertReturnCall = Expression.Call(convertRetMethod, methodCall);
182174
var body = convertReturnCall;
183175

@@ -233,8 +225,6 @@ private static InvocationExpression MethodCallExpression(
233225
var parameters = target.GetParameters();
234226

235227
var (clrIndexStart, argsLen) = contextMethod.InjectsProcess ? (1, parameters.Length - 1) : (0, parameters.Length);
236-
object[] defaultValues = new object[argsLen];
237-
var defaultsClojure = Expression.Constant(defaultValues);
238228

239229
var argsPass = new List<Expression>();
240230
argsPass.Add(instParam);
@@ -246,14 +236,18 @@ private static InvocationExpression MethodCallExpression(
246236
{
247237
var convertMethod = _genConvertParamMethod.MakeGenericMethod(parameters[clrIndex].ParameterType);
248238

239+
Expression defaultArg;
249240
if (parameters[clrIndex].HasDefaultValue)
250241
{
251-
defaultValues[bslIndex] = parameters[clrIndex].DefaultValue;
242+
defaultArg = Expression.Constant(parameters[clrIndex].DefaultValue, parameters[clrIndex].ParameterType);
243+
}
244+
else
245+
{
246+
defaultArg = Expression.Default(parameters[clrIndex].ParameterType);
252247
}
253248

254249
var indexedArg = Expression.ArrayIndex(argsParam, Expression.Constant(bslIndex));
255-
var defaultArg = Expression.ArrayIndex(defaultsClojure, Expression.Constant(bslIndex));
256-
var conversionCall = Expression.Call(convertMethod, indexedArg, defaultArg);
250+
var conversionCall = Expression.Call(convertMethod, indexedArg, defaultArg, processParam);
257251
argsPass.Add(conversionCall);
258252
}
259253

@@ -288,18 +282,16 @@ private static Expression CreateDelegateExpr(MethodInfo target)
288282
return methodClojure;
289283
}
290284

291-
// ReSharper disable once UnusedMember.Local
292-
private static T ConvertParam<T>(IValue value, object def)
285+
private static readonly MethodInfo _genConvertParamMethod =
286+
typeof(InternalMethInfo).GetMethod(nameof(ConvertParam),
287+
BindingFlags.Static | BindingFlags.NonPublic);
288+
289+
private static T ConvertParam<T>(IValue value, T def, IBslProcess process)
293290
{
294291
if (value == null || value.IsSkippedArgument())
295-
return (T)def;
292+
return def;
296293

297-
return ContextValuesMarshaller.ConvertParam<T>(value);
298-
}
299-
300-
private static IValue ConvertReturnValue<TRet>(TRet param)
301-
{
302-
return ContextValuesMarshaller.ConvertReturnValue(param);
294+
return ContextValuesMarshaller.ConvertParam<T>(value, process, def);
303295
}
304296
}
305297

src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,55 @@ This Source Code Form is subject to the terms of the
55
at http://mozilla.org/MPL/2.0/.
66
----------------------------------------------------------*/
77
using System;
8+
using System.Linq;
89
using System.Reflection;
910
using OneScript.Commons;
1011
using OneScript.Contexts;
1112
using OneScript.Exceptions;
13+
using OneScript.Execution;
1214
using OneScript.Values;
1315

1416
namespace ScriptEngine.Machine.Contexts
1517
{
1618
public static class ContextValuesMarshaller
1719
{
20+
public static MethodInfo BslParameterConverter { get; private set; }
21+
public static MethodInfo BslParameterGenericConverter { get; private set; }
22+
public static MethodInfo BslReturnValueGenericConverter { get; private set; }
23+
24+
static ContextValuesMarshaller()
25+
{
26+
BslParameterConverter = typeof(ContextValuesMarshaller).GetMethods()
27+
.First(x => x.Name == nameof(ConvertParam) && x.GetGenericArguments().Length == 0 && x.GetParameters().Length == 3);
28+
29+
BslParameterGenericConverter = typeof(ContextValuesMarshaller).GetMethods()
30+
.First(x => x.Name == nameof(ConvertParam) && x.GetGenericArguments().Length == 1 && x.GetParameters().Length == 3);
31+
32+
BslReturnValueGenericConverter = typeof(ContextValuesMarshaller).GetMethods()
33+
.First(x => x.Name == nameof(ConvertReturnValue) && x.GetGenericArguments().Length == 1);
34+
}
35+
1836
public static T ConvertParam<T>(IValue value, T defaultValue = default)
1937
{
20-
object valueObj = ConvertParam(value, typeof(T));
21-
return valueObj != null ? (T)valueObj : defaultValue;
38+
return ConvertParam<T>(value, ForbiddenBslProcess.Instance, defaultValue);
2239
}
2340

24-
public static T ConvertParamDef<T>(IValue value, T defaultValue)
41+
public static T ConvertParam<T>(IValue value, IBslProcess process, T defaultValue = default)
2542
{
26-
object valueObj = ConvertParam(value, typeof(T));
43+
object valueObj = ConvertParam(value, typeof(T), process);
2744
return valueObj != null ? (T)valueObj : defaultValue;
2845
}
29-
46+
3047
public static object ConvertParam(IValue value, Type type)
48+
{
49+
return ConvertParam(value, type, ForbiddenBslProcess.Instance);
50+
}
51+
52+
public static object ConvertParam(IValue value, Type type, IBslProcess process)
3153
{
3254
try
3355
{
34-
return ConvertValueType(value, type);
56+
return ConvertValueType(value, type, process);
3557
}
3658
catch (InvalidCastException)
3759
{
@@ -76,7 +98,7 @@ public static T ConvertValueStrict<T>(IValue value)
7698
}
7799
}
78100

79-
private static object ConvertValueType(IValue value, Type type)
101+
private static object ConvertValueType(IValue value, Type type, IBslProcess process)
80102
{
81103
object valueObj;
82104
if (value == null || value.IsSkippedArgument())
@@ -86,7 +108,7 @@ private static object ConvertValueType(IValue value, Type type)
86108

87109
if (Nullable.GetUnderlyingType(type) != null)
88110
{
89-
return ConvertValueType(value, Nullable.GetUnderlyingType(type));
111+
return ConvertValueType(value, Nullable.GetUnderlyingType(type), process);
90112
}
91113

92114
if (type == typeof(IValue))
@@ -99,7 +121,7 @@ private static object ConvertValueType(IValue value, Type type)
99121
}
100122
else if (type == typeof(string))
101123
{
102-
valueObj = value.AsString();
124+
valueObj = ((BslValue)value.GetRawValue()).ConvertToString(process);
103125
}
104126
else if (value == BslUndefinedValue.Instance)
105127
{

src/ScriptEngine/Machine/TypeFactory.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,11 @@ public class TypeFactory : ITypeFactory
2626
private readonly TypeDescriptor _systemType;
2727

2828
private Dictionary<int, InstanceConstructor> _constructorsCache = new Dictionary<int, InstanceConstructor>();
29+
private static readonly Refl.MethodInfo CopyMethod = typeof(TypeFactory)
30+
.GetMethod(nameof(CaptureVariantArgs), Refl.BindingFlags.Static | Refl.BindingFlags.InvokeMethod | Refl.BindingFlags.NonPublic);
2931

30-
private static readonly Refl.MethodInfo _typeCast =
31-
typeof(ContextValuesMarshaller).GetMethods()
32-
.First(x => x.Name == nameof(ContextValuesMarshaller.ConvertParam) && x.GetGenericArguments().Length == 0);
33-
34-
private static readonly Refl.MethodInfo _genTypeCast =
35-
typeof(ContextValuesMarshaller).GetMethods()
36-
.First(x => x.Name == nameof(ContextValuesMarshaller.ConvertParamDef) && x.GetGenericArguments().Length == 1);
37-
3832
public TypeFactory(TypeDescriptor type)
3933
{
40-
System.Diagnostics.Debug.Assert(_typeCast != null);
41-
System.Diagnostics.Debug.Assert(_genTypeCast != null);
42-
4334
_systemType = type;
4435
}
4536

@@ -112,16 +103,15 @@ private InstanceConstructor CreateConstructor(IValue[] arguments)
112103
++paramIndex;
113104
}
114105

106+
var bslProcessParameter =
107+
Expression.PropertyOrField(contextParam, nameof(TypeActivationContext.CurrentProcess));
108+
115109
for (int i = 0; i < arguments.Length; i++)
116110
{
117111
if (parameters[paramIndex].ParameterType.IsArray)
118112
{
119113
// capture all
120-
121-
var copyMethod = typeof(TypeFactory).GetMethod("CaptureVariantArgs", Refl.BindingFlags.Static | Refl.BindingFlags.InvokeMethod | Refl.BindingFlags.NonPublic);
122-
System.Diagnostics.Debug.Assert(copyMethod != null);
123-
124-
argsToPass.Add(Expression.Call(copyMethod, argsParam, Expression.Constant(i)));
114+
argsToPass.Add(Expression.Call(CopyMethod, argsParam, Expression.Constant(i)));
125115
++paramIndex;
126116
break;
127117
}
@@ -134,15 +124,22 @@ private InstanceConstructor CreateConstructor(IValue[] arguments)
134124
var conversionArg = Expression.ArrayIndex(argsParam, Expression.Constant(i));
135125
if (parameters[i].HasDefaultValue)
136126
{
137-
var convertMethod = _genTypeCast.MakeGenericMethod(parameters[i].ParameterType);
127+
var convertMethod = ContextValuesMarshaller.BslParameterGenericConverter.MakeGenericMethod(parameters[i].ParameterType);
138128
var defaultArg = Expression.Constant(parameters[i].DefaultValue, parameters[i].ParameterType);
139129

140-
var marshalledArg = Expression.Call(convertMethod, conversionArg, defaultArg);
130+
var marshalledArg = Expression.Call(convertMethod, conversionArg, bslProcessParameter, defaultArg);
141131
argsToPass.Add(marshalledArg);
142132
}
143133
else
144134
{
145-
var marshalledArg = Expression.Call(_typeCast, conversionArg, Expression.Constant(parameters[paramIndex].ParameterType));
135+
// FIXME: Сомнительно, что тут надо использовать non-generic вариант вызова
136+
// а потом делать cast в тип параметра. Кажется, что можно использовать BslParameterGenericConverter
137+
var marshalledArg = Expression.Call(
138+
ContextValuesMarshaller.BslParameterConverter,
139+
conversionArg,
140+
Expression.Constant(parameters[paramIndex].ParameterType),
141+
bslProcessParameter);
142+
146143
argsToPass.Add(Expression.Convert(marshalledArg, parameters[paramIndex].ParameterType));
147144
}
148145
}
@@ -195,7 +192,6 @@ private InstanceConstructor FallbackConstructor(Refl.MethodInfo methodInfo)
195192
};
196193
}
197194

198-
// ReSharper disable once UnusedMember.Global
199195
internal static IValue[] CaptureVariantArgs(IValue[] sourceArgs, int startingFrom)
200196
{
201197
var newArray = new IValue[sourceArgs.Length - startingFrom];

0 commit comments

Comments
 (0)