fix #2204
Изменение реализации range на InternalRange и IntRange CharRange Правки в AutoInsertCode.cs IntRange и CharRange в PABCSystem.pas - аналогично Котлину
This commit is contained in:
parent
750654fd9f
commit
228c9f9aac
|
|
@ -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<T>
|
||||
if (ImplementingInterfaces != null)
|
||||
{
|
||||
Dictionary<definition_node, definition_node> cache = new Dictionary<definition_node, definition_node>();
|
||||
List<SymbolInfo> props = new List<SymbolInfo>();
|
||||
foreach (type_node ii_tn in ImplementingInterfaces)
|
||||
{
|
||||
List<SymbolInfo> isi = ii_tn.find_in_type(name, CurrentScope);
|
||||
if (isi != null)
|
||||
{
|
||||
if (sil == null)
|
||||
sil = new List<SymbolInfo>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%MINOR%=6
|
||||
%REVISION%=2345
|
||||
%COREVERSION%=0
|
||||
%REVISION%=2352
|
||||
%MINOR%=6
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.6.0.2345
|
||||
3.6.0.2352
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.6.0.2345'
|
||||
!define VERSION '3.6.0.2352'
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -2423,6 +2423,73 @@ type
|
|||
end;
|
||||
|
||||
|
||||
type
|
||||
/// Тип диапазона целых
|
||||
IntRange = class(IEnumerable<integer>)
|
||||
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<integer> := 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<char>)
|
||||
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<char> := 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
|
||||
|
||||
|
|
|
|||
5
TestSuite/IntRangeFirst.pas
Normal file
5
TestSuite/IntRangeFirst.pas
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
begin
|
||||
var ir := InternalRange(2,5);
|
||||
|
||||
Assert(ir.Take(1).First = 2);
|
||||
end.
|
||||
12
TestSuite/errors/err0346_ResInLambda.pas
Normal file
12
TestSuite/errors/err0346_ResInLambda.pas
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function f1: byte;
|
||||
begin
|
||||
|
||||
var p: ()->() := ()->
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
|
|
@ -19545,6 +19545,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
_function_lambda_definition.return_type = null;
|
||||
}
|
||||
else _function_lambda_definition.usedkeyword = 1; // значит, это наверняка функция
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2423,6 +2423,73 @@ type
|
|||
end;
|
||||
|
||||
|
||||
type
|
||||
/// Тип диапазона целых
|
||||
IntRange = class(IEnumerable<integer>)
|
||||
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<integer> := 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<char>)
|
||||
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<char> := 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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue