Skip to content

Commit 267709c

Browse files
committed
Merge remote-tracking branch 'origin/latest' into latest
2 parents d85fb50 + 91d93e9 commit 267709c

File tree

5 files changed

+118
-54
lines changed

5 files changed

+118
-54
lines changed

src/ScriptEngine/Machine/Contexts/ContextMethodMapper.cs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -181,41 +181,43 @@ private static MethodInfo CreateMetadata(System.Reflection.MethodInfo target, Co
181181
var paramDefs = new ParameterDefinition[argNum];
182182
for (int i = 0; i < argNum; i++)
183183
{
184+
var param = parameters[i];
185+
184186
var pd = new ParameterDefinition();
185-
if (parameters[i].GetCustomAttributes(typeof(ByRefAttribute), false).Length != 0)
187+
pd.RealType = param.ParameterType;
188+
189+
if (param.GetCustomAttributes(typeof(ByRefAttribute), false).Length != 0)
186190
{
187-
if (parameters[i].ParameterType != typeof(IVariable))
188-
{
191+
if (param.ParameterType != typeof(IVariable))
189192
throw new InvalidOperationException("Attribute ByRef can be applied only on IVariable parameters");
190-
}
193+
191194
pd.IsByValue = false;
192195
}
193196
else
194197
{
195198
pd.IsByValue = true;
196199
}
197200

198-
if (parameters[i].IsOptional)
201+
if (param.HasDefaultValue)
199202
{
200203
pd.HasDefaultValue = true;
204+
pd.DefaultValue = ContextValuesMarshaller.ConvertParameterDefaultValue(param);
201205
pd.DefaultValueIndex = ParameterDefinition.UNDEFINED_VALUE_INDEX;
202206
}
203207

204208
paramDefs[i] = pd;
205-
206209
}
207210

208-
var scriptMethInfo = new ScriptEngine.Machine.MethodInfo();
209-
scriptMethInfo.IsFunction = isFunc;
210-
scriptMethInfo.IsExport = true;
211-
scriptMethInfo.IsDeprecated = binding.IsDeprecated;
212-
scriptMethInfo.ThrowOnUseDeprecated = binding.ThrowOnUse;
213-
scriptMethInfo.Name = binding.GetName();
214-
scriptMethInfo.Alias = binding.GetAlias(target.Name);
215-
216-
scriptMethInfo.Params = paramDefs;
217-
218-
return scriptMethInfo;
211+
return new MethodInfo
212+
{
213+
IsFunction = isFunc,
214+
IsExport = true,
215+
IsDeprecated = binding.IsDeprecated,
216+
ThrowOnUseDeprecated = binding.ThrowOnUse,
217+
Name = binding.GetName(),
218+
Alias = binding.GetAlias(target.Name),
219+
Params = paramDefs
220+
};
219221
}
220222

221223
private static ContextCallableDelegate<TInstance> CreateFunction(System.Reflection.MethodInfo target)

src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the
66
----------------------------------------------------------*/
77
using System;
88
using System.Linq;
9+
using System.Reflection;
910
using ScriptEngine.Machine.Values;
1011

1112
namespace ScriptEngine.Machine.Contexts
@@ -208,6 +209,15 @@ public static T ConvertWrappedEnum<T>(IValue enumeration, T defValue) where T :
208209
throw RuntimeException.InvalidArgumentValue();
209210
}
210211

212+
public static IValue ConvertParameterDefaultValue(ParameterInfo paramInfo)
213+
{
214+
if (paramInfo.DefaultValue == null)
215+
return null;
216+
217+
return ConvertReturnValue(paramInfo.DefaultValue, paramInfo.ParameterType);
218+
}
219+
220+
211221
public static IValue ConvertDynamicValue(object param)
212222
{
213223
if (param == null)

src/ScriptEngine/Machine/Core.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ public struct ParameterDefinition
217217

218218
[NonSerialized]
219219
public IValue DefaultValue;
220-
220+
public Type RealType;
221+
221222
public int DefaultValueIndex;
222223
public AnnotationDefinition[] Annotations;
223224

src/ScriptEngine/Machine/MachineInstance.cs

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ This Source Code Form is subject to the terms of the
88
using System;
99
using System.Collections.Generic;
1010
using System.Linq;
11+
using System.Runtime.CompilerServices;
1112
using OneScript.Language;
1213
using OneScript.Language.LexicalAnalysis;
1314
using ScriptEngine.Compiler;
1415
using ScriptEngine.Environment;
1516
using ScriptEngine.Machine.Values;
17+
using System.Reflection;
18+
//using System.Runtime.Remoting.Contexts;
1619

1720
namespace ScriptEngine.Machine
1821
{
@@ -1005,29 +1008,33 @@ private bool MethodCallImpl(int arg, bool asFunc)
10051008
private void CallContext(IRuntimeContextInstance instance, int index, ref MethodInfo methInfo, IValue[] argValues, bool asFunc)
10061009
{
10071010
IValue[] realArgs;
1008-
if (!instance.DynamicMethodSignatures)
1011+
if (instance.DynamicMethodSignatures)
1012+
{
1013+
realArgs = PrepareDynamicArgs(argValues);
1014+
}
1015+
else
10091016
{
10101017
realArgs = new IValue[methInfo.ArgCount];
1011-
var skippedArg = ValueFactory.CreateInvalidValueMarker();
1018+
10121019
int i = 0;
10131020
for (; i < argValues.Length; i++)
10141021
{
1015-
realArgs[i] = argValues[i];
1022+
realArgs[i] = PrepareArg(argValues[i], methInfo.Params[i], i);
10161023
}
1024+
1025+
// "Недостаточно параметров" - отсечено при компиляции
1026+
// все оставшиеся должны иметь дефолтное значение
10171027
for (; i < realArgs.Length; i++)
10181028
{
1019-
realArgs[i] = skippedArg;
1029+
realArgs[i] = methInfo.Params[i].DefaultValue;
10201030
}
10211031
}
1022-
else
1023-
{
1024-
realArgs = argValues;
1025-
}
10261032

10271033
if (asFunc)
10281034
{
10291035
instance.CallAsFunction(index, realArgs, out IValue retVal);
10301036
_operationStack.Push(retVal);
1037+
10311038
}
10321039
else
10331040
{
@@ -1036,6 +1043,52 @@ private void CallContext(IRuntimeContextInstance instance, int index, ref Method
10361043
NextInstruction();
10371044
}
10381045

1046+
private static IValue[] PrepareDynamicArgs(IValue[] factArgs)
1047+
{
1048+
var realArgs = new IValue[factArgs.Length];
1049+
for (int i = 0; i < factArgs.Length; i++)
1050+
{
1051+
var argValue = factArgs[i];
1052+
if (argValue.DataType != DataType.NotAValidValue)
1053+
{
1054+
realArgs[i] = argValue;
1055+
}
1056+
// else null
1057+
}
1058+
1059+
return realArgs;
1060+
}
1061+
1062+
private static IValue PrepareArg(IValue argValue, ParameterDefinition paramDef, int index)
1063+
{
1064+
if (argValue.DataType == DataType.NotAValidValue)
1065+
{
1066+
if (paramDef.HasDefaultValue)
1067+
{
1068+
return paramDef.DefaultValue;
1069+
}
1070+
else if (paramDef.RealType == typeof(string))
1071+
{
1072+
return ValueFactory.Create(""); // Undefined.AsString()
1073+
}
1074+
else if (!typeof(IValue).IsAssignableFrom(paramDef.RealType))
1075+
{
1076+
throw RuntimeException.MissedNthArgument(index+1);
1077+
}
1078+
}
1079+
else
1080+
{
1081+
if (paramDef.IsByValue)
1082+
return argValue.GetRawValue();
1083+
else
1084+
{
1085+
return argValue is IVariable ? argValue : Variable.Create(argValue, "");
1086+
}
1087+
}
1088+
1089+
return null;
1090+
}
1091+
10391092
private void ArgNum(int arg)
10401093
{
10411094
_operationStack.Push(ValueFactory.Create(arg));
@@ -1060,8 +1113,9 @@ private void ResolveProp(int arg)
10601113
var propName = _module.Constants[arg].AsString();
10611114
var propNum = context.FindProperty(propName);
10621115

1063-
var propReference = Variable.CreateContextPropertyReference(context, propNum, "stackvar");
1116+
var propReference = Variable.CreateContextPropertyReference(context, propNum, propName);
10641117
_operationStack.Push(propReference);
1118+
10651119
NextInstruction();
10661120
}
10671121

@@ -1110,15 +1164,7 @@ private void PrepareContextCallArguments(int arg, out IRuntimeContextInstance co
11101164

11111165
if (context.DynamicMethodSignatures)
11121166
{
1113-
argValues = new IValue[argCount];
1114-
for (int i = 0; i < argCount; i++)
1115-
{
1116-
var argValue = factArgs[i];
1117-
if (argValue.DataType != DataType.NotAValidValue)
1118-
{
1119-
argValues[i] = argValue;
1120-
}
1121-
}
1167+
argValues = PrepareDynamicArgs(factArgs);
11221168
}
11231169
else
11241170
{
@@ -1132,23 +1178,15 @@ private void PrepareContextCallArguments(int arg, out IRuntimeContextInstance co
11321178
int i = 0;
11331179
for (; i < argCount; i++)
11341180
{
1135-
var argValue = factArgs[i];
1136-
if (argValue.DataType != DataType.NotAValidValue)
1137-
{
1138-
if (methodParams[i].IsByValue)
1139-
argValues[i] = argValue.GetRawValue();
1140-
else
1141-
{
1142-
argValues[i] = argValue is IVariable ? argValue : Variable.Create(argValue, "");
1143-
}
1144-
}
1145-
else if (!methodParams[i].HasDefaultValue)
1146-
throw RuntimeException.MissedArgument();
1181+
argValues[i] = PrepareArg(factArgs[i], methodParams[i], i);
11471182
}
1183+
11481184
for (; i < methodParams.Length; i++)
11491185
{
11501186
if (!methodParams[i].HasDefaultValue)
11511187
throw RuntimeException.TooFewArgumentsPassed();
1188+
1189+
argValues[i] = methodParams[i].DefaultValue;
11521190
}
11531191
}
11541192
}
@@ -1534,7 +1572,7 @@ private void ExitTry(int arg)
15341572
NextInstruction();
15351573
}
15361574

1537-
#endregion
1575+
#endregion
15381576

15391577
#region Built-in functions
15401578

@@ -2470,7 +2508,7 @@ private void NewFunc(int argCount)
24702508

24712509
#endregion
24722510

2473-
#endregion
2511+
#endregion
24742512

24752513
private LoadedModule CompileExpressionModule(string expression)
24762514
{

src/ScriptEngine/Machine/RuntimeExceptions.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@ public static RuntimeException DeprecatedMethodCall(string name)
4646

4747
public static RuntimeException ConvertToNumberException()
4848
{
49-
return new RuntimeException("Преобразование к типу 'Число' не поддерживается");
49+
return new TypeConvertionException("Число");
5050
}
5151

5252
public static RuntimeException ConvertToBooleanException()
5353
{
54-
return new RuntimeException("Преобразование к типу 'Булево' не поддерживается");
54+
return new TypeConvertionException("Булево");
5555
}
5656

5757
public static RuntimeException ConvertToDateException()
5858
{
59-
return new RuntimeException("Преобразование к типу 'Дата' не поддерживается");
59+
return new TypeConvertionException("Дата");
6060
}
61-
61+
6262
public static RuntimeException PropIsNotReadableException(string prop)
6363
{
6464
return PropertyAccessException.GetPropIsNotReadableException(prop);
@@ -104,6 +104,11 @@ public static RuntimeException MissedArgument()
104104
return new RuntimeException("Пропущен обязательный параметр");
105105
}
106106

107+
public static RuntimeException MissedNthArgument(int argNum)
108+
{
109+
return new RuntimeException($"Пропущен обязательный параметр номер {argNum}" );
110+
}
111+
107112
public static RuntimeException InvalidArgumentType()
108113
{
109114
return new RuntimeException("Неверный тип аргумента");
@@ -214,6 +219,14 @@ public ScriptInterruptionException(int exitCode) : base("Script interrupted")
214219
public int ExitCode { get; private set; }
215220
}
216221

222+
public class TypeConvertionException : RuntimeException
223+
{
224+
public TypeConvertionException(string typename)
225+
: base($"Преобразование к типу '{typename}' не поддерживается")
226+
{
227+
}
228+
}
229+
217230
public class ValueMarshallingException : RuntimeException
218231
{
219232
public ValueMarshallingException() : this("Неклассифицированная ошибка маршаллинга значений")

0 commit comments

Comments
 (0)