diff --git a/Compiler/PCU/PCUWrappers.cs b/Compiler/PCU/PCUWrappers.cs index 0dbd6c451..2578024c9 100644 --- a/Compiler/PCU/PCUWrappers.cs +++ b/Compiler/PCU/PCUWrappers.cs @@ -321,6 +321,35 @@ namespace PascalABCCompiler.PCU return base_type.find_in_type(name, CurrentScope, null, no_search_in_extension_methods); else if (name == compiler_string_consts.deconstruct_method_name) return SystemLibrary.SystemLibrary.object_type.find_in_type(name, CurrentScope, null, no_search_in_extension_methods); + + // SSM перенес из common_type_node (types.cs 2116) - без этого не работали методы расширения последовательностей для типов в pcu, реализующих IEnumerable + if (ImplementingInterfaces != null) + { + Dictionary cache = new Dictionary(); + List props = new List(); + foreach (type_node ii_tn in ImplementingInterfaces) + { + List isi = ii_tn.find_in_type(name, CurrentScope); + if (isi != null) + { + if (sil == null) + sil = new List(); + foreach (SymbolInfo si in isi) + { + if (!cache.ContainsKey(si.sym_info)) + { + if (si.sym_info is function_node && (si.sym_info as function_node).is_extension_method + && sil.FindIndex(ssi => ssi.sym_info == si.sym_info) == -1) // SSM 12.12.18 - за счёт методов интерфейсов тоже могут добавляться одинаковые - исключаем их + sil.Add(si); + cache.Add(si.sym_info, si.sym_info); + } + } + } + } + if (sil != null && sil.Count == 0) + sil = null; + } + return sil; } diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 08afe685e..ae81fcd83 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "6"; public const string Build = "0"; - public const string Revision = "2345"; + public const string Revision = "2352"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 00929a048..7c425d8f9 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ -%MINOR%=6 -%REVISION%=2345 %COREVERSION%=0 +%REVISION%=2352 +%MINOR%=6 %MAJOR%=3 diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index c356a013c..be62b4c43 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.6.0.2345 +3.6.0.2352 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 02b8b29b5..f0f36c1eb 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.6.0.2345' +!define VERSION '3.6.0.2352' diff --git a/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs b/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs index fca4fcccd..2aa4dca23 100644 --- a/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs +++ b/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs @@ -33,7 +33,7 @@ namespace SyntaxVisitors.SugarVisitors el.Add(diap.right, diap.right.source_context); // Проблема в том, что тут тоже надо перепрошивать Parent! - var mc = method_call.NewP(dot_node.NewP(new ident("PABCSystem", diap.source_context), new ident("Range", diap.source_context), diap.source_context), el, diap.source_context); + var mc = method_call.NewP(dot_node.NewP(new ident("PABCSystem", diap.source_context), new ident("InternalRange", diap.source_context), diap.source_context), el, diap.source_context); var sug = sugared_addressed_value.NewP(diap, mc, diap.source_context); diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index fbec79e8c..33a7b8c95 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -2423,6 +2423,73 @@ type end; +type + /// Тип диапазона целых + IntRange = class(IEnumerable) + private + l,h: integer; + public + constructor(l,h: integer); + begin + Self.l := l; + Self.h := h; + end; + property Low: integer read l; + property High: integer read h; + + static function operator in(x: integer; r: IntRange): boolean := (x >= r.l) and (x <= r.h); + static function operator=(r1,r2: IntRange): boolean := (r1.l = r2.l) and (r1.h = r2.h); + + function IsEmpty: boolean := l<=h; + + function GetEnumerator(): IEnumerator := Range(l,h).GetEnumerator; + function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Range(l,h).GetEnumerator; + + function ToString: string; override := $'({l},{h})'; + function Equals(o: Object): boolean; override; + begin + var r2 := IntRange(o); + Result := (l = r2.l) and (h = r2.h); + end; + function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode; + end; + + /// Тип диапазона символов + CharRange = class(IEnumerable) + private + l,h: char; + public + constructor(l,h: char); + begin + Self.l := l; + Self.h := h; + end; + property Low: char read l; + property High: char read h; + + static function operator in(x: char; r: CharRange): boolean := (x >= r.l) and (x <= r.h); + static function operator=(r1,r2: CharRange): boolean := (r1.l = r2.l) and (r1.h = r2.h); + + function IsEmpty: boolean := l<=h; + + function GetEnumerator(): IEnumerator := Range(l,h).GetEnumerator; + function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Range(l,h).GetEnumerator; + + function ToString: string; override := $'({l},{h})'; + function Equals(o: Object): boolean; override; + begin + var r2 := CharRange(o); + Result := (l = r2.l) and (h = r2.h); + end; + function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode; + end; + +///-- +function InternalRange(l,r: integer): IntRange; +///-- +function InternalRange(l,r: char): CharRange; + + // ----------------------------------------------------- // Internal procedures for PABCRTL.dll // ----------------------------------------------------- @@ -4884,8 +4951,18 @@ begin else begin _IsPipedRedirectedQuery := True; - _IsPipedRedirected := Console.IsInputRedirected and (CurrentIOSystem.GetType = typeof(IOStandardSystem)); - Result := _IsPipedRedirected; + var pi := typeof(Console).GetProperty('IsInputRedirected'); + if pi = nil then + begin + _IsPipedRedirected := False; // просто работаем без буфера на старых системах + Result := _IsPipedRedirected; + end + else + begin + var IsInputRedirected := boolean(pi?.GetValue(nil,nil)); + _IsPipedRedirected := IsInputRedirected {Console.IsInputRedirected} and (CurrentIOSystem.GetType = typeof(IOStandardSystem)); + Result := _IsPipedRedirected; + end; end; end; @@ -12404,6 +12481,11 @@ begin Result := ''; end; +function InternalRange(l,r: integer): IntRange := new IntRange(l,r); + +function InternalRange(l,r: char): CharRange := new CharRange(l,r); + + //------------------------------------------------------------------------------ //OMP diff --git a/TestSuite/IntRangeFirst.pas b/TestSuite/IntRangeFirst.pas new file mode 100644 index 000000000..a6ea1bec9 --- /dev/null +++ b/TestSuite/IntRangeFirst.pas @@ -0,0 +1,5 @@ +begin + var ir := InternalRange(2,5); + + Assert(ir.Take(1).First = 2); +end. \ No newline at end of file diff --git a/TestSuite/errors/err0346_ResInLambda.pas b/TestSuite/errors/err0346_ResInLambda.pas new file mode 100644 index 000000000..1a5f5c5c0 --- /dev/null +++ b/TestSuite/errors/err0346_ResInLambda.pas @@ -0,0 +1,12 @@ +function f1: byte; +begin + + var p: ()->() := ()-> + begin + Result := 0; + end; + +end; + +begin +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 9c84e74cd..4eb367f8f 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -19545,6 +19545,7 @@ namespace PascalABCCompiler.TreeConverter { _function_lambda_definition.return_type = null; } + else _function_lambda_definition.usedkeyword = 1; // значит, это наверняка функция } } diff --git a/VisualPascalABCNET/AutoInsertCode/AutoInsertCode.cs b/VisualPascalABCNET/AutoInsertCode/AutoInsertCode.cs index d32002f1b..dfe430529 100644 --- a/VisualPascalABCNET/AutoInsertCode/AutoInsertCode.cs +++ b/VisualPascalABCNET/AutoInsertCode/AutoInsertCode.cs @@ -17,7 +17,7 @@ namespace VisualPascalABC var ta = CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.TextArea; var doc = ta.Document; if (lineNum < doc.TotalNumberOfLines) - return TextUtilities.GetLineAsString(doc, lineNum); + return TextUtilities.GetLineAsString(doc, lineNum); else return null; } @@ -99,9 +99,10 @@ namespace VisualPascalABC int start = TextUtilities.FindPrevWordStart(editor.Document, caret.Offset); // Нужно, чтобы в Text было последнее слово в строке !!! Исключение - когда в следующей надо сделать просто сдвиг var Text = editor.Document.GetText(start, caret.Offset - start).TrimEnd(); + var TextToLower = Text.ToLower(); //var curStrEnd = TextUtilities.GetLineAsString(editor.Document, caret.Line).Substring(caret.Column); - if (Text.ToLower() == "begin") + if (TextToLower == "begin") { string cur, next, prev; GetCurNextLines(out cur, out next, out prev); @@ -116,7 +117,8 @@ namespace VisualPascalABC // Проанализируем предыдущий оператор по первому слову var pst = prev?.TrimStart().ToLower(); if (pst != null) - if (pst.StartsWith("if") || pst.StartsWith("for") || pst.StartsWith("loop") || pst.StartsWith("with") || pst.StartsWith("on") || pst.StartsWith("while") || pst.StartsWith("else") || pst.StartsWith("foreach")) // потом улучшу - для нескольких выборов + //if (pst.StartsWith("if") || pst.StartsWith("for") || pst.StartsWith("loop") || pst.StartsWith("with") || pst.StartsWith("on") || pst.StartsWith("while") || pst.StartsWith("else") || pst.StartsWith("foreach")) // потом улучшу - для нескольких выборов + if (Regex.IsMatch(pst, "^(if|else|for|loop|while|foreach|with|on)")) { // Надо удалить в текущей строке пробелы чтобы выровнять begin по if var iprev = Indent(prev); @@ -146,7 +148,7 @@ namespace VisualPascalABC return true; } - else if (Text.ToLower() == "repeat") // repeat .. until + else if (TextToLower == "repeat") // repeat .. until { string cur, next, prev; GetCurNextLines(out cur, out next, out prev); @@ -164,7 +166,7 @@ namespace VisualPascalABC return true; } - else if (Text.ToLower() == "class" || Text.ToLower() == "record") // class .. end, record .. end + else if (Regex.IsMatch(TextToLower,"class|record")) // class .. end, record .. end { string cur, next, prev; GetCurNextLines(out cur, out next, out prev); @@ -182,7 +184,7 @@ namespace VisualPascalABC return true; } - else if (Text.ToLower() == "of") + else if (TextToLower == "of") { string cur, next, prev; GetCurNextLines(out cur, out next, out prev); @@ -200,25 +202,37 @@ namespace VisualPascalABC return true; } - else if (Text.ToLower() == "then" || Text.ToLower() == "else" || Text.ToLower() == "do" - || Text.ToLower() == "try" || Text.ToLower() == "except" || Text.ToLower() == "finally" - || Text.ToLower() == "var") + else if (Regex.IsMatch(TextToLower, "then|else|do|try|except|finally|var")) { + if (ta.Caret.Line > 0 && TextToLower == "else") + { + var prevSeg = doc.GetLineSegment(ta.Caret.Line - 1); + var prev = GetLine(ta.Caret.Line - 1).TrimEnd(); + + if (prev[prev.Length-1] == ';') + { + doc.Replace(prevSeg.Offset + prevSeg.Length - 1, 1, ""); + } + } + var cur = GetLine(ta.Caret.Line); var icur = Indent(cur); ta.InsertString("\n" + Spaces(icur + 2)); + return true; } - else + + else { string cur, next, prev; GetCurNextLines(out cur, out next, out prev); if (ta.Caret.Column >= cur.Length) { + var prevTrimEnd = prev.TrimEnd(); // если prev заканчивается на then, а cur не начинается с begin, то отступ назад - if ((prev.TrimEnd().EndsWith("then",StringComparison.InvariantCultureIgnoreCase) || - prev.TrimEnd().EndsWith("else", StringComparison.InvariantCultureIgnoreCase) || - prev.TrimEnd().EndsWith("do", StringComparison.InvariantCultureIgnoreCase)) + if ((prevTrimEnd.EndsWith("then",StringComparison.InvariantCultureIgnoreCase) || + prevTrimEnd.EndsWith("else", StringComparison.InvariantCultureIgnoreCase) || + prevTrimEnd.EndsWith("do", StringComparison.InvariantCultureIgnoreCase)) && !(cur.TrimStart().StartsWith("begin", StringComparison.InvariantCultureIgnoreCase))) { diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index fbec79e8c..33a7b8c95 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -2423,6 +2423,73 @@ type end; +type + /// Тип диапазона целых + IntRange = class(IEnumerable) + private + l,h: integer; + public + constructor(l,h: integer); + begin + Self.l := l; + Self.h := h; + end; + property Low: integer read l; + property High: integer read h; + + static function operator in(x: integer; r: IntRange): boolean := (x >= r.l) and (x <= r.h); + static function operator=(r1,r2: IntRange): boolean := (r1.l = r2.l) and (r1.h = r2.h); + + function IsEmpty: boolean := l<=h; + + function GetEnumerator(): IEnumerator := Range(l,h).GetEnumerator; + function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Range(l,h).GetEnumerator; + + function ToString: string; override := $'({l},{h})'; + function Equals(o: Object): boolean; override; + begin + var r2 := IntRange(o); + Result := (l = r2.l) and (h = r2.h); + end; + function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode; + end; + + /// Тип диапазона символов + CharRange = class(IEnumerable) + private + l,h: char; + public + constructor(l,h: char); + begin + Self.l := l; + Self.h := h; + end; + property Low: char read l; + property High: char read h; + + static function operator in(x: char; r: CharRange): boolean := (x >= r.l) and (x <= r.h); + static function operator=(r1,r2: CharRange): boolean := (r1.l = r2.l) and (r1.h = r2.h); + + function IsEmpty: boolean := l<=h; + + function GetEnumerator(): IEnumerator := Range(l,h).GetEnumerator; + function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Range(l,h).GetEnumerator; + + function ToString: string; override := $'({l},{h})'; + function Equals(o: Object): boolean; override; + begin + var r2 := CharRange(o); + Result := (l = r2.l) and (h = r2.h); + end; + function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode; + end; + +///-- +function InternalRange(l,r: integer): IntRange; +///-- +function InternalRange(l,r: char): CharRange; + + // ----------------------------------------------------- // Internal procedures for PABCRTL.dll // ----------------------------------------------------- @@ -4884,8 +4951,18 @@ begin else begin _IsPipedRedirectedQuery := True; - _IsPipedRedirected := Console.IsInputRedirected and (CurrentIOSystem.GetType = typeof(IOStandardSystem)); - Result := _IsPipedRedirected; + var pi := typeof(Console).GetProperty('IsInputRedirected'); + if pi = nil then + begin + _IsPipedRedirected := False; // просто работаем без буфера на старых системах + Result := _IsPipedRedirected; + end + else + begin + var IsInputRedirected := boolean(pi?.GetValue(nil,nil)); + _IsPipedRedirected := IsInputRedirected {Console.IsInputRedirected} and (CurrentIOSystem.GetType = typeof(IOStandardSystem)); + Result := _IsPipedRedirected; + end; end; end; @@ -12404,6 +12481,11 @@ begin Result := ''; end; +function InternalRange(l,r: integer): IntRange := new IntRange(l,r); + +function InternalRange(l,r: char): CharRange := new CharRange(l,r); + + //------------------------------------------------------------------------------ //OMP