diff --git a/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs b/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs index c623b4c0a..6fdb45233 100644 --- a/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs +++ b/src/OneScript.Core/Exceptions/IExceptionInfoFactory.cs @@ -16,7 +16,7 @@ namespace OneScript.Exceptions /// public interface IExceptionInfoFactory { - BslObjectValue GetExceptionInfo(Exception exception); + BslValue GetExceptionInfo(Exception exception); string GetExceptionDescription(IRuntimeContextInstance exceptionInfo); diff --git a/src/OneScript.Native/Compiler/ExpressionHelpers.cs b/src/OneScript.Native/Compiler/ExpressionHelpers.cs index 8ed0f479e..9da05ee85 100644 --- a/src/OneScript.Native/Compiler/ExpressionHelpers.cs +++ b/src/OneScript.Native/Compiler/ExpressionHelpers.cs @@ -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), diff --git a/src/OneScript.Native/Compiler/MethodCompiler.cs b/src/OneScript.Native/Compiler/MethodCompiler.cs index a2be74b8c..c925b8bf8 100644 --- a/src/OneScript.Native/Compiler/MethodCompiler.cs +++ b/src/OneScript.Native/Compiler/MethodCompiler.cs @@ -142,7 +142,7 @@ private void CompileFragment(BslSyntaxNode node, Action 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) @@ -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(); - args.Add(target); - args.AddRange(PrepareDynamicCallArguments(call.ArgumentList)); - - var csharpArgs = new List(); - 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 PrepareDynamicCallArguments(BslSyntaxNode argList) @@ -1167,44 +1124,49 @@ private IEnumerable 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(); - args.Add(target); + var args = new List + { + target + }; args.AddRange(PrepareDynamicCallArguments(call.ArgumentList)); - var csharpArgs = new List(); - csharpArgs.Add(CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default)); + var csharpArgs = new List + { + CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default) + }; csharpArgs.AddRange(args.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, default))); var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember( @@ -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) @@ -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; @@ -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) @@ -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); @@ -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( @@ -1417,9 +1400,10 @@ private Expression DirectConversionCall(CallNode node, Type type) return ExpressionHelpers.ConvertToType( ConvertToExpressionTree(node.ArgumentList.Children[0].Children[0]), type); - } - - private List PrepareCallArguments(BslSyntaxNode argList, ParameterInfo[] declaredParameters, bool injectsProcess) + } + + private List PrepareCallArguments(BslSyntaxNode argList, ParameterInfo[] declaredParameters, + bool injectsProcess, bool passUndef = false) { var factArguments = new List(); @@ -1474,6 +1458,10 @@ private List 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( @@ -1544,12 +1532,12 @@ protected override void VisitNewObjectCreation(NewObjectNode node) } else { - parameters = new Expression[0]; + parameters = []; } if (node.IsDynamic) { - var typeName = ConvertToExpressionTree(node.TypeNameNode); + var typeName = ExpressionHelpers.ConvertToType(ConvertToExpressionTree(node.TypeNameNode), typeof(string)); var call = ExpressionHelpers.ConstructorCall(CurrentTypeManager, services, typeName, _processParameter, parameters); _statementBuildParts.Push(call); } diff --git a/src/OneScript.Native/Runtime/CallableMethod.cs b/src/OneScript.Native/Runtime/CallableMethod.cs index f61237aad..f44f3b138 100644 --- a/src/OneScript.Native/Runtime/CallableMethod.cs +++ b/src/OneScript.Native/Runtime/CallableMethod.cs @@ -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; @@ -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 { @@ -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(); diff --git a/src/OneScript.Native/Runtime/DynamicOperations.cs b/src/OneScript.Native/Runtime/DynamicOperations.cs index 13289a4c2..af8c9ca86 100644 --- a/src/OneScript.Native/Runtime/DynamicOperations.cs +++ b/src/OneScript.Native/Runtime/DynamicOperations.cs @@ -134,7 +134,7 @@ public static T StrictConstructorCall(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) diff --git a/src/OneScript.Native/Runtime/NativeClassInstanceWrapper.cs b/src/OneScript.Native/Runtime/NativeClassInstanceWrapper.cs deleted file mode 100644 index 4a69fef6e..000000000 --- a/src/OneScript.Native/Runtime/NativeClassInstanceWrapper.cs +++ /dev/null @@ -1,20 +0,0 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -using System; -using OneScript.Contexts; - -namespace OneScript.Native.Runtime -{ - /// - /// Этот класс можно удалить, заменив все обращения к нему на IAttachableContext - /// - [Obsolete("This class can be removed, replace all usages with IAttachableContext")] - internal class NativeClassInstanceWrapper - { - public IAttachableContext Context { get; set; } - } -} diff --git a/src/ScriptEngine/Machine/ExceptionInfoFactory.cs b/src/ScriptEngine/Machine/ExceptionInfoFactory.cs index bcbd04ed3..aa7eed7cd 100644 --- a/src/ScriptEngine/Machine/ExceptionInfoFactory.cs +++ b/src/ScriptEngine/Machine/ExceptionInfoFactory.cs @@ -27,7 +27,7 @@ public ExceptionInfoFactory(IBslProcessFactory processFactory) _processFactory = processFactory; } - public BslObjectValue GetExceptionInfo(Exception exception) + public BslValue GetExceptionInfo(Exception exception) { if (exception == null) {