diff --git a/src/OneScript.Core/Compilation/Binding/BindingExtensions.cs b/src/OneScript.Core/Compilation/Binding/BindingExtensions.cs index 6c30c4961..7f3998257 100644 --- a/src/OneScript.Core/Compilation/Binding/BindingExtensions.cs +++ b/src/OneScript.Core/Compilation/Binding/BindingExtensions.cs @@ -4,7 +4,11 @@ This Source Code Form is subject to the terms of the was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ + +using System.Linq; +using System.Reflection; using OneScript.Contexts; +using OneScript.Language.SyntaxAnalysis.AstNodes; using OneScript.Runtime.Binding; using OneScript.Values; @@ -40,5 +44,16 @@ public static IFieldSymbol ToSymbol(this BslFieldInfo info) { return new BslFieldSymbol { Field = info }; } + + public static bool IsUniqueMethod(this SymbolTable table, MethodNode astNode) + { + var isKnown = table.TryFindMethodBinding(astNode.Signature.MethodName, out _); + if (!isKnown) + { + return true; + } + + return astNode.Annotations.Any(a => BslOverrideAttribute.AcceptsIdentifier(a.Name)); + } } } diff --git a/src/OneScript.Core/Compilation/Binding/BslOverrideAttribute.cs b/src/OneScript.Core/Compilation/Binding/BslOverrideAttribute.cs new file mode 100644 index 000000000..d2a361640 --- /dev/null +++ b/src/OneScript.Core/Compilation/Binding/BslOverrideAttribute.cs @@ -0,0 +1,23 @@ +/*---------------------------------------------------------- +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.Localization; + +namespace OneScript.Compilation.Binding +{ + [AttributeUsage(AttributeTargets.Method)] + public class BslOverrideAttribute : Attribute + { + public static readonly BilingualString OverrideAttributeName = new BilingualString("Переопределить", "Override"); + + public static bool AcceptsIdentifier(string identifier) + { + return OverrideAttributeName.ContainsString(identifier); + } + } +} \ No newline at end of file diff --git a/src/OneScript.Language/Localization/BilingualString.cs b/src/OneScript.Language/Localization/BilingualString.cs index a4aaf9f01..6c7105576 100644 --- a/src/OneScript.Language/Localization/BilingualString.cs +++ b/src/OneScript.Language/Localization/BilingualString.cs @@ -5,11 +5,12 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ +using System; using System.Globalization; namespace OneScript.Localization { - public class BilingualString + public class BilingualString : IEquatable { private static readonly CultureInfo RussianCulture; @@ -67,5 +68,25 @@ public static string Localize(string russian, string english) return russian; } + + public bool Equals(BilingualString other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Russian == other.Russian && English == other.English; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((BilingualString)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Russian, English); + } } } \ No newline at end of file diff --git a/src/OneScript.Language/Localization/LocalizationExtensions.cs b/src/OneScript.Language/Localization/LocalizationExtensions.cs new file mode 100644 index 000000000..1bb625242 --- /dev/null +++ b/src/OneScript.Language/Localization/LocalizationExtensions.cs @@ -0,0 +1,24 @@ +/*---------------------------------------------------------- +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; + +namespace OneScript.Localization +{ + public static class LocalizationExtensions + { + public static bool ContainsString(this BilingualString bi, string sample) + { + return ContainsString(bi, sample, StringComparison.CurrentCultureIgnoreCase); + } + + public static bool ContainsString(this BilingualString bi, string sample, StringComparison comparison) + { + return bi.Russian.Equals(sample, comparison) || bi.English.Equals(sample, comparison); + } + } +} \ No newline at end of file diff --git a/src/OneScript.Native/Compiler/CompilerHelpers.cs b/src/OneScript.Native/Compiler/CompilerHelpers.cs index 2afe69439..6159fcc5f 100644 --- a/src/OneScript.Native/Compiler/CompilerHelpers.cs +++ b/src/OneScript.Native/Compiler/CompilerHelpers.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; +using OneScript.Compilation.Binding; using OneScript.Contexts; using OneScript.Language.LexicalAnalysis; using OneScript.Language.SyntaxAnalysis.AstNodes; @@ -49,10 +50,15 @@ public static object ClrValueFromLiteral(in Lexem lex) public static IEnumerable GetAnnotations(IEnumerable annotations) { - // Возможно будут какие-то маппинги на системные атрибуты, не только на BslAnnotation - // поэтому возвращаем Attribute[] а не BslAnnotation[] + return annotations.Select(a => + { + if (BslOverrideAttribute.AcceptsIdentifier(a.Name)) + { + return new BslOverrideAttribute(); + } - return annotations.Select(GetBslAnnotation).ToList(); + return GetBslAnnotation(a); + }).ToList(); } public static BslAnnotationAttribute GetBslAnnotation(AnnotationNode node) diff --git a/src/OneScript.Native/Compiler/ModuleCompiler.cs b/src/OneScript.Native/Compiler/ModuleCompiler.cs index 61acb2044..2b295034e 100644 --- a/src/OneScript.Native/Compiler/ModuleCompiler.cs +++ b/src/OneScript.Native/Compiler/ModuleCompiler.cs @@ -79,7 +79,7 @@ private void RegisterLocalMethods(BslSyntaxNode module) foreach (var methodNode in methodsSection.Children.Cast()) { var signature = methodNode.Signature; - if (Symbols.TryFindMethodBinding(signature.MethodName, out _)) + if (!Symbols.IsUniqueMethod(methodNode)) { AddError(LocalizedErrors.DuplicateMethodDefinition(signature.MethodName), signature.Location); continue; diff --git a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs index baa80d944..4cb64a755 100644 --- a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs +++ b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs @@ -287,7 +287,7 @@ protected override void VisitMethod(MethodNode methodNode) methodInfo.SetRuntimeParameters(entryPoint, GetVariableNames(methodCtx)); SymbolBinding binding; - if (!_ctx.TryFindMethodBinding(signature.MethodName, out _)) + if (_ctx.IsUniqueMethod(methodNode)) { binding = _ctx.DefineMethod(methodInfo.ToSymbol()); } @@ -1103,14 +1103,21 @@ private void VisitConstant(in Lexem constant) AddCommand(OperationCode.PushConst, num); } - private IEnumerable GetAnnotationAttributes(AnnotatableNode node) + private IEnumerable GetAnnotationAttributes(AnnotatableNode node) { - var mappedAnnotations = new List(); + var mappedAnnotations = new List(); foreach (var annotation in node.Annotations) { - var anno = new BslAnnotationAttribute(annotation.Name); - anno.SetParameters(GetAnnotationParameters(annotation)); - mappedAnnotations.Add(anno); + if (BslOverrideAttribute.AcceptsIdentifier(annotation.Name)) + { + mappedAnnotations.Add(new BslOverrideAttribute()); + } + else + { + var anno = new BslAnnotationAttribute(annotation.Name); + anno.SetParameters(GetAnnotationParameters(annotation)); + mappedAnnotations.Add(anno); + } } return mappedAnnotations; diff --git a/tests/engine-behaviors.os b/tests/engine-behaviors.os index f661c603c..f1088a9bd 100644 --- a/tests/engine-behaviors.os +++ b/tests/engine-behaviors.os @@ -53,6 +53,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПараметровПоСсылке"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСравнениеНаБольшеМеньше"); ВсеТесты.Добавить("ТестДолжен_ПроверитьНевозможностьПереопределенияГлобальногоКонтекста"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьВозможностьПереопределенияГлобальногоКонтекста"); Возврат ВсеТесты; @@ -709,3 +710,22 @@ юТест.ПроверитьКодСОшибкой("#native" + Символы.ПС + Код, "СтрНайти"); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьВозможностьПереопределенияГлобальногоКонтекста() Экспорт + + Код = "&Переопределить + |Функция СтрНайти(знач Стр1, знач Стр2) + | Возврат -1; + |КонецФункции + | + |Функция Проверить() Экспорт + | Возврат СтрНайти(""1"", ""1""); + |КонецФункции"; + + СкриптСтек = ЗагрузитьСценарийИзСтроки(Код); + СкриптНатив = ЗагрузитьСценарийИзСтроки("#native" + Символы.ПС + Код); + + юТест.ПроверитьРавенство(-1, СкриптСтек.Проверить()); + юТест.ПроверитьРавенство(-1, СкриптНатив.Проверить()); + +КонецПроцедуры