Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace OneScript.Exceptions
/// </summary>
public interface IExceptionInfoFactory
{
BslObjectValue GetExceptionInfo(Exception exception);
BslValue GetExceptionInfo(Exception exception);

string GetExceptionDescription(IRuntimeContextInstance exceptionInfo);

Expand Down
8 changes: 1 addition & 7 deletions src/OneScript.Native/Compiler/ExpressionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,18 +595,12 @@ public static Expression CallOfInstanceMethod(Expression instance, string name,

public static Expression AccessModuleVariable(ParameterExpression thisArg, int variableIndex)
{
var contextProperty = PropertiesCache.GetOrAdd(
typeof(NativeClassInstanceWrapper),
nameof(NativeClassInstanceWrapper.Context),
BindingFlags.Instance | BindingFlags.Public);

var contextAccess = Expression.Property(thisArg, contextProperty);
var getVariableMethod = OperationsCache.GetOrAdd(
typeof(IAttachableContext),
nameof(IAttachableContext.GetVariable),
BindingFlags.Instance | BindingFlags.Public);

var iVariable = Expression.Call(contextAccess, getVariableMethod, Expression.Constant(variableIndex));
var iVariable = Expression.Call(thisArg, getVariableMethod, Expression.Constant(variableIndex));
var valueProperty = PropertiesCache.GetOrAdd(
typeof(IValueReference),
nameof(IValueReference.BslValue),
Expand Down
162 changes: 75 additions & 87 deletions src/OneScript.Native/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private void CompileFragment(BslSyntaxNode node, Action<BslSyntaxNode> visitor)
private void FillParameterVariables()
{
_declaredParameters = _method.GetBslParameters();
_thisParameter = _method.IsInstance ? Expression.Parameter(typeof(NativeClassInstanceWrapper), "$this") : null;
_thisParameter = _method.IsInstance ? Expression.Parameter(typeof(IAttachableContext), "$this") : null;

var localScope = Symbols.GetScope(Symbols.ScopeCount-1);
foreach (var parameter in _declaredParameters)
Expand Down Expand Up @@ -1107,56 +1107,13 @@ private static bool InjectedProcessNeeded(MethodInfo methodInfo)
}

protected override void VisitObjectProcedureCall(BslSyntaxNode node)
{
var target = _statementBuildParts.Pop();
var call = (CallNode) node;

var targetType = target.Type;
var name = call.Identifier.GetIdentifier();
if (targetType.IsObjectValue())
{
var methodInfo = FindMethodOfType(node, targetType, name);
var injectProcess = InjectedProcessNeeded(methodInfo);
var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), injectProcess);

_blocks.Add(Expression.Call(target, methodInfo, args));
}
else if (targetType.IsContext())
{
var contextCall = ExpressionHelpers.CallContextMethod(target, name, _processParameter,
PrepareDynamicCallArguments(call.ArgumentList));
_blocks.Add(contextCall);
}
else if (targetType.IsValue())
{
var contextCall = ExpressionHelpers.TryCallContextMethod(target, name, _processParameter,
PrepareDynamicCallArguments(call.ArgumentList));
_blocks.Add(contextCall);
}
else if (target is DynamicExpression)
{
var args = new List<Expression>();
args.Add(target);
args.AddRange(PrepareDynamicCallArguments(call.ArgumentList));

var csharpArgs = new List<CSharpArgumentInfo>();
csharpArgs.Add(CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default));
csharpArgs.AddRange(args.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default)));

var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.InvokeSimpleName,
name,
null,
typeof(BslObjectValue),
csharpArgs);
{
_blocks.Add(CreateObjectMethodCall(node));
}

var objectExpr = Expression.Dynamic(binder, typeof(object), args);
_blocks.Add(ExpressionHelpers.ConvertToType(objectExpr, typeof(BslValue)));
}
else
{
AddError(NativeCompilerErrors.TypeIsNotAnObjectType(targetType), node.Location);
}
protected override void VisitObjectFunctionCall(BslSyntaxNode node)
{
_statementBuildParts.Push(CreateObjectMethodCall(node, true));
}

private IEnumerable<Expression> PrepareDynamicCallArguments(BslSyntaxNode argList)
Expand All @@ -1167,44 +1124,49 @@ private IEnumerable<Expression> PrepareDynamicCallArguments(BslSyntaxNode argLis
: Expression.Constant(BslSkippedParameterValue.Instance));
}

protected override void VisitObjectFunctionCall(BslSyntaxNode node)
{
private Expression CreateObjectMethodCall(BslSyntaxNode node, bool asFunction = false)
{
var target = _statementBuildParts.Pop();
var call = (CallNode) node;

var call = (CallNode)node;
var targetType = target.Type;
var name = call.Identifier.GetIdentifier();
if (targetType.IsObjectValue())
{
var methodInfo = FindMethodOfType(node, targetType, name);
if (methodInfo.ReturnType == typeof(void))
{
throw new NativeCompilerException(BilingualString.Localize(
$"Метод {targetType}.{name} не является функцией",
$"Method {targetType}.{name} is not a function"), ToCodePosition(node.Location));
}

var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), InjectedProcessNeeded(methodInfo));
_statementBuildParts.Push(Expression.Call(target, methodInfo, args));
if (targetType.IsObjectValue()
&& TryFindMethodOfType(targetType, name, out var methodInfo))
{
if (asFunction && methodInfo?.ReturnType == typeof(void))
{
throw new NativeCompilerException(BilingualString.Localize(
$"Метод {targetType}.{name} не является функцией",
$"Method {targetType}.{name} is not a function"), ToCodePosition(node.Location));
}

var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), InjectedProcessNeeded(methodInfo));
return Expression.Call(target, methodInfo, args);
}
else if (targetType.IsContext())

if (targetType.IsContext())
{
_statementBuildParts.Push(ExpressionHelpers.CallContextMethod(target, name, _processParameter, PrepareDynamicCallArguments(call.ArgumentList)));
return ExpressionHelpers.CallContextMethod(target, name, _processParameter,
PrepareDynamicCallArguments(call.ArgumentList));
}
else if (targetType.IsValue())
{
var contextCall = ExpressionHelpers.TryCallContextMethod(target, name, _processParameter,
return ExpressionHelpers.TryCallContextMethod(target, name, _processParameter,
PrepareDynamicCallArguments(call.ArgumentList));
_statementBuildParts.Push(contextCall);
}
else if (target is DynamicExpression)
{
var args = new List<Expression>();
args.Add(target);
var args = new List<Expression>
{
target
};
args.AddRange(PrepareDynamicCallArguments(call.ArgumentList));

var csharpArgs = new List<CSharpArgumentInfo>();
csharpArgs.Add(CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default));
var csharpArgs = new List<CSharpArgumentInfo>
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default)
};
csharpArgs.AddRange(args.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default)));

var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
Expand All @@ -1215,12 +1177,11 @@ protected override void VisitObjectFunctionCall(BslSyntaxNode node)
csharpArgs);

var objectExpr = Expression.Dynamic(binder, typeof(object), args);
_statementBuildParts.Push(ExpressionHelpers.ConvertToType(objectExpr, typeof(BslValue)));
}
else
{
AddError(NativeCompilerErrors.TypeIsNotAnObjectType(targetType), node.Location);
return ExpressionHelpers.ConvertToType(objectExpr, typeof(BslValue));
}

AddError(NativeCompilerErrors.TypeIsNotAnObjectType(targetType), node.Location);
return null;
}

private MethodInfo FindMethodOfType(BslSyntaxNode node, Type targetType, string name)
Expand All @@ -1240,6 +1201,21 @@ private MethodInfo FindMethodOfType(BslSyntaxNode node, Type targetType, string
return methodInfo;
}

private bool TryFindMethodOfType(Type targetType, string name, out MethodInfo methodInfo)
{
try
{
methodInfo = _methodsCache.GetOrAdd(targetType, name);
}
catch (InvalidOperationException)
{
methodInfo = null;
return false;
}

return true;
}

private PropertyInfo TryFindPropertyOfType(BslSyntaxNode node, Type targetType, string name)
{
PropertyInfo propertyInfo;
Expand Down Expand Up @@ -1281,15 +1257,21 @@ private Expression CreateMethodCall(CallNode node)
}

var symbol = Symbols.GetScope(binding.ScopeNumber).Methods[binding.MemberNumber];
var args = PrepareCallArguments(node.ArgumentList, symbol.Method.GetParameters(), InjectedProcessNeeded(symbol.Method));
var args = PrepareCallArguments(node.ArgumentList, symbol.Method.GetParameters(),
InjectedProcessNeeded(symbol.Method), IsModuleScope(binding.ScopeNumber));

var methodInfo = symbol.Method;
if (methodInfo is ContextMethodInfo contextMethod)
{
return DirectClrCall(
var call = DirectClrCall(
GetMethodBinding(binding, symbol),
contextMethod.GetWrappedMethod(),
args);

if (call.Type == typeof(IValue))
return Expression.TypeAs(call, typeof(BslValue));

return call;
}

if (methodInfo is BslNativeMethodInfo nativeMethod)
Expand Down Expand Up @@ -1328,9 +1310,8 @@ private Expression CreateBuiltInFunctionCall(CallNode node)
result = DirectConversionCall(node, typeof(DateTime));
break;
case Token.Type:
CheckArgumentsCount(node.ArgumentList, 1);
result = ExpressionHelpers.TypeByNameCall(CurrentTypeManager,
ConvertToExpressionTree(node.ArgumentList.Children[0].Children[0]));
var strType = DirectConversionCall(node, typeof(string));
result = ExpressionHelpers.TypeByNameCall(CurrentTypeManager, strType);
break;
case Token.ExceptionInfo:
CheckArgumentsCount(node.ArgumentList, 0);
Expand Down Expand Up @@ -1364,7 +1345,9 @@ private Expression GetRuntimeExceptionDescription()
var excVariable = _blocks.GetCurrentBlock().CurrentException;
Expression factoryArgument;
// нас вызвали вне попытки-исключения
factoryArgument = excVariable == null ? Expression.Constant(null, typeof(IRuntimeContextInstance)) : GetRuntimeExceptionObject();
//factoryArgument = excVariable == null ? Expression.Constant(null, typeof(IRuntimeContextInstance)) : GetRuntimeExceptionObject();
factoryArgument = excVariable == null ? Expression.Constant(null, typeof(IRuntimeContextInstance))
: ExpressionHelpers.ConvertToType(GetRuntimeExceptionObject(), typeof(IRuntimeContextInstance));

var factory = Expression.Constant(ExceptionInfoFactory);
return ExpressionHelpers.CallOfInstanceMethod(
Expand Down Expand Up @@ -1417,9 +1400,10 @@ private Expression DirectConversionCall(CallNode node, Type type)
return ExpressionHelpers.ConvertToType(
ConvertToExpressionTree(node.ArgumentList.Children[0].Children[0]),
type);
}

private List<Expression> PrepareCallArguments(BslSyntaxNode argList, ParameterInfo[] declaredParameters, bool injectsProcess)
}

private List<Expression> PrepareCallArguments(BslSyntaxNode argList, ParameterInfo[] declaredParameters,
bool injectsProcess, bool passUndef = false)
{
var factArguments = new List<Expression>();

Expand Down Expand Up @@ -1474,6 +1458,10 @@ private List<Expression> PrepareCallArguments(BslSyntaxNode argList, ParameterIn
{
factArguments.Add(Expression.Constant(declaredParam.DefaultValue, declaredParam.ParameterType));
}
else if (passUndef)
{
factArguments.Add(Expression.Constant(BslUndefinedValue.Instance, declaredParam.ParameterType));
}
else
{
var errText = new BilingualString(
Expand Down
19 changes: 6 additions & 13 deletions src/OneScript.Native/Runtime/CallableMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal class CallableMethod
{
private readonly BslNativeMethodInfo _method;

private delegate BslValue NativeCallable(NativeClassInstanceWrapper target, BslValue[] args, IBslProcess process);
private delegate BslValue NativeCallable(IAttachableContext target, BslValue[] args, IBslProcess process);

private NativeCallable _delegate;

Expand All @@ -47,23 +47,16 @@ public BslValue Invoke(IBslProcess process, object target, BslValue[] args)
return _delegate.Invoke(callableWrapper, args, process);
}

private NativeClassInstanceWrapper GetCallableWrapper(object obj)
private IAttachableContext GetCallableWrapper(object obj)
{
NativeClassInstanceWrapper callableWrapper;
IAttachableContext callableWrapper;
if (_method.IsInstance)
{
if (obj == null)
throw new InvalidOperationException($"Method {_method.Name} is not static and requires target");
if (obj is NativeClassInstanceWrapper w)
if (obj is IAttachableContext context)
{
callableWrapper = w;
}
else if (obj is IAttachableContext context)
{
callableWrapper = new NativeClassInstanceWrapper
{
Context = context
};
callableWrapper = context;
}
else
{
Expand All @@ -86,7 +79,7 @@ private static NativeCallable CreateDelegate(BslNativeMethodInfo method)
if (method.Implementation == default)
throw new InvalidOperationException("Method has no implementation");

var targetParam = Expression.Parameter(typeof(NativeClassInstanceWrapper));
var targetParam = Expression.Parameter(typeof(IAttachableContext));
var arrayOfValuesParam = Expression.Parameter(typeof(BslValue[]));
var processParam = Expression.Parameter(typeof(IBslProcess));
var convertedAccessList = new List<Expression>();
Expand Down
2 changes: 1 addition & 1 deletion src/OneScript.Native/Runtime/DynamicOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public static T StrictConstructorCall<T>(ITypeManager typeManager, IServiceConta
where T : BslValue
=> (T)ConstructorCall(typeManager, services, typeName, process, args);

public static BslObjectValue GetExceptionInfo(IExceptionInfoFactory factory, Exception e)
public static BslValue GetExceptionInfo(IExceptionInfoFactory factory, Exception e)
=> factory.GetExceptionInfo(e);

public static BslTypeValue GetTypeByName(ITypeManager manager, string name)
Expand Down
20 changes: 0 additions & 20 deletions src/OneScript.Native/Runtime/NativeClassInstanceWrapper.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/ScriptEngine/Machine/ExceptionInfoFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public ExceptionInfoFactory(IBslProcessFactory processFactory)
_processFactory = processFactory;
}

public BslObjectValue GetExceptionInfo(Exception exception)
public BslValue GetExceptionInfo(Exception exception)
{
if (exception == null)
{
Expand Down