fix #1053
Вложенные безымянные записи теперь снова разрешены, но запрещено захватывать имена из неглобального контекста
This commit is contained in:
parent
c204054176
commit
8545817173
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "6";
|
||||
public const string Build = "2";
|
||||
public const string Revision = "2368";
|
||||
public const string Revision = "2374";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=2
|
||||
%REVISION%=2368
|
||||
%REVISION%=2374
|
||||
%MINOR%=6
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
|||
//
|
||||
// This CSharp output file generated by Gardens Point LEX
|
||||
// Version: 1.1.3.301
|
||||
// Machine: DESKTOP-P4NLNB1
|
||||
// DateTime: 2/10/2020 2:41:45 PM
|
||||
// UserName: fatco
|
||||
// Machine: DESKTOP-G8V08V4
|
||||
// DateTime: 07.03.2020 10:31:43
|
||||
// UserName: ?????????
|
||||
// GPLEX input file <ABCPascal.lex>
|
||||
// GPLEX frame file <embedded resource>
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1550,7 +1550,7 @@ object_type
|
|||
{
|
||||
var cd = NewObjectType((class_attribute)$1, $2, $3 as named_type_reference_list, $4 as where_definition_list, $5 as class_body_list, @$);
|
||||
$$ = cd;
|
||||
var tt = cd.DescendantNodes().OfType<class_definition>().Where(cld => cld.keyword == class_keyword.Record);
|
||||
/*var tt = cd.DescendantNodes().OfType<class_definition>().Where(cld => cld.keyword == class_keyword.Record);
|
||||
if (tt.Count()>0)
|
||||
{
|
||||
foreach (var ttt in tt)
|
||||
|
|
@ -1558,7 +1558,7 @@ object_type
|
|||
var sc = ttt.source_context;
|
||||
parsertools.AddErrorFromResource("NESTED_RECORD_DEFINITIONS_ARE_FORBIDDEN", new LexLocation(sc.begin_position.line_num, sc.begin_position.column_num-1, sc.end_position.line_num, sc.end_position.column_num, sc.FileName));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// (see accompanying GPPGcopyright.rtf)
|
||||
|
||||
// GPPG version 1.3.6
|
||||
// Machine: DESKTOP-P4NLNB1
|
||||
// DateTime: 2/10/2020 2:41:46 PM
|
||||
// UserName: fatco
|
||||
// Machine: DESKTOP-G8V08V4
|
||||
// DateTime: 07.03.2020 10:31:44
|
||||
// UserName: ?????????
|
||||
// Input file <ABCPascal.y>
|
||||
|
||||
// options: no-lines gplex
|
||||
|
|
@ -3973,7 +3973,7 @@ public partial class GPPGParser: ShiftReduceParser<PascalABCSavParser.Union, Lex
|
|||
{
|
||||
var cd = NewObjectType((class_attribute)ValueStack[ValueStack.Depth-5].ob, ValueStack[ValueStack.Depth-4].ti, ValueStack[ValueStack.Depth-3].stn as named_type_reference_list, ValueStack[ValueStack.Depth-2].stn as where_definition_list, ValueStack[ValueStack.Depth-1].stn as class_body_list, CurrentLocationSpan);
|
||||
CurrentSemanticValue.td = cd;
|
||||
var tt = cd.DescendantNodes().OfType<class_definition>().Where(cld => cld.keyword == class_keyword.Record);
|
||||
/*var tt = cd.DescendantNodes().OfType<class_definition>().Where(cld => cld.keyword == class_keyword.Record);
|
||||
if (tt.Count()>0)
|
||||
{
|
||||
foreach (var ttt in tt)
|
||||
|
|
@ -3981,7 +3981,7 @@ public partial class GPPGParser: ShiftReduceParser<PascalABCSavParser.Union, Lex
|
|||
var sc = ttt.source_context;
|
||||
parsertools.AddErrorFromResource("NESTED_RECORD_DEFINITIONS_ARE_FORBIDDEN", new LexLocation(sc.begin_position.line_num, sc.begin_position.column_num-1, sc.end_position.line_num, sc.end_position.column_num, sc.FileName));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case 284: // record_type -> tkRecord, optional_base_classes, optional_where_section,
|
||||
|
|
|
|||
|
|
@ -262,5 +262,6 @@ script=
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.6.2.2368
|
||||
3.6.2.2374
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.6.2.2368'
|
||||
!define VERSION '3.6.2.2374'
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Text;
|
|||
using PascalABCCompiler.SyntaxTree;
|
||||
using SyntaxVisitors;
|
||||
using SyntaxVisitors.SugarVisitors;
|
||||
using SyntaxVisitors.CheckingVisitors;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||
{
|
||||
|
|
@ -22,6 +23,9 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
// new range - до всего! До выноса выражения с лямбдой из foreach
|
||||
NewRangeDesugarVisitor.New.ProcessNode(root);
|
||||
|
||||
// Unnamed Records перенёс сюда
|
||||
UnnamedRecordsCheckVisitor.New.ProcessNode(root);
|
||||
|
||||
// Выносим выражения с лямбдами из заголовка foreach
|
||||
StandOutExprWithLambdaInForeachSequenceVisitor.New.ProcessNode(root);
|
||||
VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer.New.ProcessNode(root); // SSM bug fix #1147
|
||||
|
|
|
|||
|
|
@ -0,0 +1,266 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors.CheckingVisitors
|
||||
{
|
||||
public class CollectDefNamesFromMostUpperLocalContextVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
public List<ident> idents = new List<ident>();
|
||||
public class_definition StartUnnamedRecord; // безымянная запись, до которой и для которой будем искать имена
|
||||
public static CollectDefNamesFromMostUpperLocalContextVisitor New(class_definition cd)
|
||||
{
|
||||
return new CollectDefNamesFromMostUpperLocalContextVisitor(cd);
|
||||
}
|
||||
public CollectDefNamesFromMostUpperLocalContextVisitor(class_definition cd)
|
||||
{
|
||||
StartUnnamedRecord = cd;
|
||||
}
|
||||
public void Add(ident id)
|
||||
{
|
||||
if (idents.FindIndex(x => string.Compare(x.name, id.name, true) == 0) == -1)
|
||||
idents.Add(id);
|
||||
}
|
||||
public void AddIdentList(ident_list idl)
|
||||
{
|
||||
foreach (var id in idl.idents)
|
||||
Add(id);
|
||||
}
|
||||
public void AddProcHeader(procedure_header h)
|
||||
{
|
||||
Add(h.name.meth_name);
|
||||
if (h.template_args != null)
|
||||
AddIdentList(h.template_args);
|
||||
if (h.parameters != null)
|
||||
foreach (var tp in h.parameters.params_list)
|
||||
{
|
||||
AddIdentList(tp.idents);
|
||||
}
|
||||
}
|
||||
|
||||
/*public override void visit(template_type_name ttn) // при определении типа
|
||||
{
|
||||
Add(ttn);
|
||||
AddIdentList(ttn.template_args);
|
||||
}*/
|
||||
public override void visit(var_def_statement vds)
|
||||
{
|
||||
AddIdentList(vds.vars);
|
||||
ProcessNode(vds.vars_type);
|
||||
}
|
||||
/*public override void visit(typed_parameters tp)
|
||||
{
|
||||
AddIdentList(tp.idents);
|
||||
}*/
|
||||
public override void visit(procedure_header h)
|
||||
{
|
||||
AddProcHeader(h);
|
||||
}
|
||||
public override void visit(function_header h)
|
||||
{
|
||||
AddProcHeader(h);
|
||||
}
|
||||
public override void visit(typed_const_definition cd)
|
||||
{
|
||||
Add(cd.const_name);
|
||||
}
|
||||
public override void visit(simple_const_definition cd)
|
||||
{
|
||||
Add(cd.const_name);
|
||||
}
|
||||
public override void visit(type_declaration td)
|
||||
{
|
||||
Add(td.type_name);
|
||||
if (td.type_name is template_type_name ttn)
|
||||
{
|
||||
AddIdentList(ttn.template_args);
|
||||
}
|
||||
ProcessNode(td.type_def);
|
||||
}
|
||||
|
||||
// var_def_statement.idents +
|
||||
// typed_parameters (параметры процедуры-функции) +
|
||||
// method_name +
|
||||
// template_type_name +
|
||||
// type_declaration.type_name
|
||||
// const_definition.constant_name +
|
||||
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
if (cd == StartUnnamedRecord)
|
||||
{
|
||||
//cd = cd;
|
||||
// то внутри нее не искать - мы как раз с ней и проверяем пересечение имен
|
||||
}
|
||||
else if (StartUnnamedRecord.source_context.In(cd.source_context))
|
||||
{
|
||||
DefaultVisit(cd);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class OneUnnamedRecordCaptureNamesVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
// Имена, захваченные записью. Их мы будем искать затем во внешних контекстах
|
||||
// Сюда не включаются имена во вложенных безымянных записях
|
||||
// Сюда не включаются имена, являющиеся определениями (в данном случае это только определения полей)
|
||||
public List<ident> idents = new List<ident>();
|
||||
public class_definition StartUnnamedRecord;
|
||||
public static OneUnnamedRecordCaptureNamesVisitor New(class_definition cd)
|
||||
{
|
||||
return new OneUnnamedRecordCaptureNamesVisitor(cd);
|
||||
}
|
||||
public OneUnnamedRecordCaptureNamesVisitor(class_definition cd)
|
||||
{
|
||||
StartUnnamedRecord = cd;
|
||||
}
|
||||
// Накопленные имена типов надо будет сравнивать только с именами в секции type (в процедуре) и с именами в параметрах внешних обобщений (процедур и классов)
|
||||
public void CollectNames()
|
||||
{
|
||||
var defBlocks = StartUnnamedRecord.body.class_def_blocks;
|
||||
// Теперь известно, что остался ровно один class_def_block
|
||||
foreach (var member in defBlocks[0].members)
|
||||
{
|
||||
var q = member as var_def_statement;
|
||||
var id = q.vars.idents[0]; // это просто имя
|
||||
var type = q.vars_type;
|
||||
var initValue = q.inital_value;
|
||||
// idents.Add(id); - вот как раз не надо добавлять определения - только использования!!!
|
||||
ProcessNode(type);
|
||||
if (initValue != null)
|
||||
ProcessNode(initValue);
|
||||
}
|
||||
}
|
||||
public override void visit(ident id)
|
||||
{
|
||||
if (idents.FindIndex(x => string.Compare(x.name,id.name,true) == 0) == -1)
|
||||
idents.Add(id);
|
||||
}
|
||||
public override void visit(named_type_reference ntr)
|
||||
{
|
||||
visit(ntr.names[0]);
|
||||
if (ntr is template_type_reference ttr)
|
||||
{
|
||||
foreach (var tt in ttr.params_list.params_list)
|
||||
ProcessNode(tt);
|
||||
}
|
||||
}
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
if (cd.keyword == class_keyword.Record && cd.Parent is var_def_statement) // безымянная запись
|
||||
{
|
||||
// то пропустить её - она вложенная, мы её уже обошли
|
||||
}
|
||||
else base.visit(cd);
|
||||
}
|
||||
|
||||
}
|
||||
public class UnnamedRecordsCheckVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
public static UnnamedRecordsCheckVisitor New
|
||||
{
|
||||
get { return new UnnamedRecordsCheckVisitor(); }
|
||||
}
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
var cd = st as class_definition;
|
||||
if (cd == null)
|
||||
return;
|
||||
if (cd.keyword == class_keyword.Record && cd.Parent is var_def_statement) // безымянная запись
|
||||
{
|
||||
if (cd.class_parents != null && cd.class_parents.Count > 0)
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE", cd.class_parents[0].source_context);
|
||||
|
||||
var defBlocks = cd.body.class_def_blocks;
|
||||
|
||||
if (defBlocks[0].access_mod.access_level != access_modifer.public_modifer)
|
||||
{
|
||||
var f = cd.body.class_def_blocks.First();
|
||||
var loc = f.source_context;
|
||||
if (loc == null)
|
||||
loc = cd.source_context;
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION", loc);
|
||||
}
|
||||
|
||||
if (defBlocks.Count > 1)
|
||||
{
|
||||
var el1 = cd.body.class_def_blocks.ElementAt(1);
|
||||
var loc = el1.access_mod.source_context;
|
||||
if (loc == null)
|
||||
loc = cd.source_context;
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS", loc);
|
||||
}
|
||||
|
||||
// здесь уже известно, что defBlocks.Count = 1 - пройтись по этому блоку и проверить, нет ли методов или свойств
|
||||
|
||||
foreach (var d in defBlocks[0].members)
|
||||
{
|
||||
var pd = d as procedure_definition;
|
||||
if (pd != null)
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_METHODS", pd.source_context);
|
||||
var sp = d as simple_property;
|
||||
if (sp != null)
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES", sp.source_context);
|
||||
}
|
||||
|
||||
var cdvis = OneUnnamedRecordCaptureNamesVisitor.New(cd);
|
||||
cdvis.CollectNames();
|
||||
// после накопления имен подниматься по внешнему контексту, пропуская эту запись, и искать переменные и типы
|
||||
// Переменные - в var_def_statement. Типы - в type_definition, в типовых параметрах обобщенных процедур и в типовых параметрах имен типов
|
||||
|
||||
// Подняться вверх до program_module и запомнить последнюю class_definition, procedure_definition
|
||||
// или class_definition или type_declaration если это именованный тип
|
||||
// То есть у class_definition проверять Parent - если это type_declaration, то смотреть на имя типа, а если это var_def_statement, то смотреть на имена переменных
|
||||
|
||||
syntax_tree_node MostUpperNodeWithNotGlobalNames = null;
|
||||
|
||||
syntax_tree_node sn = cd;
|
||||
while ((sn != null) && !(sn is program_module))
|
||||
{
|
||||
sn = sn.Parent;
|
||||
if (sn is procedure_definition)
|
||||
MostUpperNodeWithNotGlobalNames = sn;
|
||||
if (sn is class_definition)
|
||||
{
|
||||
MostUpperNodeWithNotGlobalNames = sn;
|
||||
sn = sn.Parent;
|
||||
if (sn is type_declaration || sn is var_def_statement)
|
||||
MostUpperNodeWithNotGlobalNames = sn;
|
||||
}
|
||||
}
|
||||
|
||||
var localsvis = CollectDefNamesFromMostUpperLocalContextVisitor.New(cd);
|
||||
if (MostUpperNodeWithNotGlobalNames != null)
|
||||
{
|
||||
localsvis.ProcessNode(MostUpperNodeWithNotGlobalNames);
|
||||
}
|
||||
|
||||
var lvi = localsvis.idents.Select(id => id.name).ToArray();
|
||||
var cvi = cdvis.idents;
|
||||
|
||||
// Теперь проверим пересечение
|
||||
foreach (var id in cvi)
|
||||
{
|
||||
var s = id.name;
|
||||
foreach (var lname in lvi)
|
||||
{
|
||||
if (string.Compare(s,lname,true)==0)
|
||||
{
|
||||
throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
<Compile Include="BaseVisitors\HasStatementVisitor.cs" />
|
||||
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
|
||||
<Compile Include="ChangeWhileVisitor.cs" />
|
||||
<Compile Include="CheckingVisitors\UnnamedRecordsCheckErrorsVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeHelperClasses.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1Helper.cs" />
|
||||
|
|
@ -116,9 +117,7 @@
|
|||
<Name>YieldHelpers</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="CheckingVisitors\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,6 +39,9 @@ uses System.Runtime.CompilerServices;
|
|||
//===================================
|
||||
// Обязательно сделать до следующего пула:
|
||||
|
||||
//ToDo Тесты всех фич модуля
|
||||
//ToDo И в каждом сделать по несколько выполнений, на случай плавающий ошибок
|
||||
|
||||
//===================================
|
||||
// Запланированное:
|
||||
|
||||
|
|
@ -97,8 +100,6 @@ uses System.Runtime.CompilerServices;
|
|||
//ToDo Пройтись по всем функциям OpenCL, посмотреть функционал каких не доступен из OpenCLABC
|
||||
// - у Kernel.Exec несколько параметров не используются. Стоит использовать
|
||||
|
||||
//ToDo Тесты всех фич модуля
|
||||
|
||||
//===================================
|
||||
|
||||
//ToDo issue компилятора:
|
||||
|
|
@ -137,7 +138,7 @@ type
|
|||
|
||||
ProgramCode = class;
|
||||
|
||||
DeviceTypeFlags = OpenCL.DeviceTypeFlags;
|
||||
DeviceType = OpenCL.DeviceType;
|
||||
|
||||
{$endregion pre def}
|
||||
|
||||
|
|
@ -145,10 +146,11 @@ type
|
|||
|
||||
__NativUtils = static class
|
||||
|
||||
static function CopyToUnm<TRecord>(a: TRecord): ^TRecord; where TRecord: record;
|
||||
static function CopyToUnm<TRecord>(a: TRecord): IntPtr; where TRecord: record;
|
||||
begin
|
||||
Result := pointer(Marshal.AllocHGlobal(Marshal.SizeOf&<TRecord>));
|
||||
Result^ := a;
|
||||
Result := Marshal.AllocHGlobal(Marshal.SizeOf&<TRecord>);
|
||||
var res: ^TRecord := pointer(Result);
|
||||
res^ := a;
|
||||
end;
|
||||
|
||||
static function AsPtr<T>(p: pointer): ^T := p;
|
||||
|
|
@ -156,10 +158,10 @@ type
|
|||
static function GCHndAlloc(o: object) :=
|
||||
CopyToUnm(GCHandle.Alloc(o));
|
||||
|
||||
static procedure GCHndFree(gc_hnd_ptr: pointer);
|
||||
static procedure GCHndFree(gc_hnd_ptr: IntPtr);
|
||||
begin
|
||||
AsPtr&<GCHandle>(gc_hnd_ptr)^.Free;
|
||||
Marshal.FreeHGlobal(IntPtr(gc_hnd_ptr));
|
||||
AsPtr&<GCHandle>(pointer(gc_hnd_ptr))^.Free;
|
||||
Marshal.FreeHGlobal(gc_hnd_ptr);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
|
@ -199,14 +201,8 @@ type
|
|||
|
||||
public static procedure operator+=(l: __EventList; ev: __EventList);
|
||||
begin
|
||||
{$ifdef DebugMode}
|
||||
for var i := 0 to ev.count-1 do
|
||||
l += ev[i];
|
||||
exit;
|
||||
{$endif DebugMode}
|
||||
if ev.count=0 then exit;
|
||||
System.Buffer.BlockCopy( ev.evs,0, l.evs,l.count*cl_event.Size, ev.count*cl_event.Size );
|
||||
l.count += ev.count;
|
||||
end;
|
||||
|
||||
public static function operator+(l1,l2: __EventList): __EventList;
|
||||
|
|
@ -231,12 +227,12 @@ type
|
|||
for var i := 0 to count-1 do
|
||||
cl.ReleaseEvent(evs[i]).RaiseIfError;
|
||||
|
||||
public static procedure AttachCallback(ev: cl_event; cb: Event_Callback);
|
||||
public static procedure AttachCallback(ev: cl_event; cb: Event_Callback; tsk: CLTaskBase);
|
||||
public static procedure AttachCallback(ev: cl_event; cb: EventCallback);
|
||||
public static procedure AttachCallback(ev: cl_event; cb: EventCallback; tsk: CLTaskBase);
|
||||
|
||||
///cb должен иметь глобальный try и вызывать "state.RaiseIfError" и "__NativUtils.GCHndFree(data)",
|
||||
///А "cl.ReleaseEvent" если и вызывать - то только на результате вызова AttachCallback
|
||||
public function AttachCallback(cb: Event_Callback; c: Context; var cq: cl_command_queue): cl_event;
|
||||
public function AttachCallback(cb: EventCallback; c: Context; var cq: cl_command_queue): cl_event;
|
||||
|
||||
end;
|
||||
|
||||
|
|
@ -255,7 +251,7 @@ type
|
|||
|
||||
function WaitAndGetBase: object;
|
||||
|
||||
function AttachCallbackBase(cb: Event_Callback; c: Context; var cq: cl_command_queue): __IQueueRes;
|
||||
function AttachCallbackBase(cb: EventCallback; c: Context; var cq: cl_command_queue): __IQueueRes;
|
||||
|
||||
end;
|
||||
__QueueRes<T> = record(__IQueueRes)
|
||||
|
|
@ -306,13 +302,13 @@ type
|
|||
|
||||
end;
|
||||
|
||||
function AttachCallback(cb: Event_Callback; c: Context; var cq: cl_command_queue): __QueueRes<T>;
|
||||
function AttachCallback(cb: EventCallback; c: Context; var cq: cl_command_queue): __QueueRes<T>;
|
||||
begin
|
||||
Result.res := self.res;
|
||||
Result.res_f := self.res_f;
|
||||
Result.ev := self.ev.AttachCallback(cb, c, cq);
|
||||
end;
|
||||
function AttachCallbackBase(cb: Event_Callback; c: Context; var cq: cl_command_queue): __IQueueRes := AttachCallback(cb, c, cq);
|
||||
function AttachCallbackBase(cb: EventCallback; c: Context; var cq: cl_command_queue): __IQueueRes := AttachCallback(cb, c, cq);
|
||||
|
||||
end;
|
||||
|
||||
|
|
@ -513,7 +509,7 @@ type
|
|||
if err.IS_ERROR then AddErr(new OpenCLException(err.ToString));
|
||||
|
||||
protected procedure AddErr(st: CommandExecutionStatus) :=
|
||||
if st.IS_ERROR then AddErr(new OpenCLException(st.GetError.ToString));
|
||||
if st.IS_ERROR then AddErr(new OpenCLException(ErrorCode.Create(st).ToString));
|
||||
|
||||
/// Возвращает True если очередь уже завершилась
|
||||
protected function AddEventHandler<T>(var ev: T; cb: T): boolean; where T: Delegate;
|
||||
|
|
@ -1466,24 +1462,24 @@ type
|
|||
_def_cont := new Context;
|
||||
except
|
||||
try
|
||||
_def_cont := new Context(DeviceTypeFlags.All); // если нету GPU - попытаться хотя бы для чего то инициализировать
|
||||
_def_cont := new Context(DeviceType.DEVICE_TYPE_ALL); // если нету GPU - попытаться хотя бы для чего то инициализировать
|
||||
except
|
||||
_def_cont := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
public constructor := Create(DeviceTypeFlags.GPU);
|
||||
public constructor := Create(DeviceType.DEVICE_TYPE_GPU);
|
||||
|
||||
public constructor(dt: DeviceTypeFlags);
|
||||
public constructor(dt: DeviceType);
|
||||
begin
|
||||
var ec: ErrorCode;
|
||||
|
||||
var _platform: cl_platform_id;
|
||||
cl.GetPlatformIDs(1, @_platform, nil).RaiseIfError;
|
||||
cl.GetPlatformIDs(1, _platform, IntPtr.Zero).RaiseIfError;
|
||||
|
||||
cl.GetDeviceIDs(_platform, dt, 1, @_device, nil).RaiseIfError;
|
||||
cl.GetDeviceIDs(_platform, dt, 1, _device, IntPtr.Zero).RaiseIfError;
|
||||
|
||||
_context := cl.CreateContext(nil, 1, @_device, nil, nil, @ec);
|
||||
_context := cl.CreateContext(IntPtr.Zero, 1, _device, nil, IntPtr.Zero, ec);
|
||||
ec.RaiseIfError;
|
||||
|
||||
need_finnalize := true;
|
||||
|
|
@ -1492,7 +1488,7 @@ type
|
|||
public constructor(context: cl_context);
|
||||
begin
|
||||
|
||||
cl.GetContextInfo(context, ContextInfoType.CL_CONTEXT_DEVICES, new UIntPtr(IntPtr.Size), @_device, nil).RaiseIfError;
|
||||
cl.GetContextInfo(context, ContextInfo.CONTEXT_DEVICES, new UIntPtr(IntPtr.Size), _device, IntPtr.Zero).RaiseIfError;
|
||||
|
||||
_context := context;
|
||||
end;
|
||||
|
|
@ -1533,7 +1529,7 @@ type
|
|||
self._program := cl.CreateProgramWithSource(c._context, files_texts.Length, files_texts, files_texts.ConvertAll(s->new UIntPtr(s.Length)), ec);
|
||||
ec.RaiseIfError;
|
||||
|
||||
cl.BuildProgram(self._program, 1, @c._device, nil,nil,nil).RaiseIfError;
|
||||
cl.BuildProgram(self._program, 1,c._device, nil, nil,IntPtr.Zero).RaiseIfError;
|
||||
|
||||
end;
|
||||
|
||||
|
|
@ -1548,12 +1544,13 @@ type
|
|||
|
||||
public function GetAllKernels: Dictionary<string, Kernel>;
|
||||
begin
|
||||
// Можно и "cl.CreateKernelsInProgram", но тогда имена придётся получать отдельно, а они нужны
|
||||
|
||||
var names_char_len: UIntPtr;
|
||||
cl.GetProgramInfo(_program, ProgramInfoType.NUM_KERNELS, new UIntPtr(UIntPtr.Size), @names_char_len, nil).RaiseIfError;
|
||||
cl.GetProgramInfo(_program, ProgramInfo.PROGRAM_KERNEL_NAMES, UIntPtr.Zero,IntPtr.Zero, names_char_len).RaiseIfError;
|
||||
|
||||
var names_ptr := Marshal.AllocHGlobal(IntPtr(pointer(names_char_len))+1);
|
||||
cl.GetProgramInfo(_program, ProgramInfoType.KERNEL_NAMES, names_char_len, pointer(names_ptr), nil).RaiseIfError;
|
||||
var names_ptr := Marshal.AllocHGlobal(IntPtr(pointer(names_char_len)));
|
||||
cl.GetProgramInfo(_program, ProgramInfo.PROGRAM_KERNEL_NAMES, names_char_len,names_ptr, IntPtr.Zero).RaiseIfError;
|
||||
|
||||
var names := Marshal.PtrToStringAnsi(names_ptr).Split(';');
|
||||
Marshal.FreeHGlobal(names_ptr);
|
||||
|
|
@ -1571,14 +1568,10 @@ type
|
|||
public function Serialize: array of byte;
|
||||
begin
|
||||
var bytes_count: UIntPtr;
|
||||
cl.GetProgramInfo(_program, ProgramInfoType.BINARY_SIZES, new UIntPtr(UIntPtr.Size), @bytes_count, nil).RaiseIfError;
|
||||
cl.GetProgramInfo(_program, ProgramInfo.PROGRAM_BINARY_SIZES, new UIntPtr(UIntPtr.Size),bytes_count, IntPtr.Zero).RaiseIfError;
|
||||
|
||||
var bytes_mem := Marshal.AllocHGlobal(IntPtr(pointer(bytes_count)));
|
||||
cl.GetProgramInfo(_program, ProgramInfoType.BINARIES, new UIntPtr(UIntPtr.Size), @bytes_mem, nil).RaiseIfError;
|
||||
|
||||
Result := new byte[bytes_count.ToUInt64()];
|
||||
Marshal.Copy(bytes_mem,Result, 0,Result.Length);
|
||||
Marshal.FreeHGlobal(bytes_mem);
|
||||
Result := new byte[bytes_count.ToUInt64];
|
||||
cl.GetProgramInfo(_program, ProgramInfo.PROGRAM_BINARIES, bytes_count,Result[0], IntPtr.Zero).RaiseIfError;
|
||||
|
||||
end;
|
||||
|
||||
|
|
@ -1597,17 +1590,16 @@ type
|
|||
|
||||
public static function Deserialize(c: Context; bin: array of byte): ProgramCode;
|
||||
begin
|
||||
var ec: ErrorCode;
|
||||
|
||||
Result := new ProgramCode;
|
||||
|
||||
var gchnd := GCHandle.Alloc(bin, GCHandleType.Pinned);
|
||||
var bin_mem: ^byte := pointer(gchnd.AddrOfPinnedObject);
|
||||
var bin_len := new UIntPtr(bin.Length);
|
||||
|
||||
Result._program := cl.CreateProgramWithBinary(c._context,1,@c._device, @bin_len, @bin_mem, nil, @ec);
|
||||
var bin_arr: array of array of byte;
|
||||
SetLength(bin_arr,1);
|
||||
bin_arr[0] := bin;
|
||||
|
||||
var ec: ErrorCode;
|
||||
Result._program := cl.CreateProgramWithBinary(c._context,1,c._device, bin_len,bin_arr, IntPtr.Zero,ec);
|
||||
ec.RaiseIfError;
|
||||
gchnd.Free;
|
||||
|
||||
end;
|
||||
|
||||
|
|
@ -1833,12 +1825,12 @@ end;
|
|||
|
||||
{$endregion CommandQueue}
|
||||
|
||||
static procedure __EventList.AttachCallback(ev: cl_event; cb: Event_Callback) :=
|
||||
static procedure __EventList.AttachCallback(ev: cl_event; cb: EventCallback) :=
|
||||
cl.SetEventCallback(ev, CommandExecutionStatus.COMPLETE, cb, __NativUtils.GCHndAlloc(cb)).RaiseIfError;
|
||||
static procedure __EventList.AttachCallback(ev: cl_event; cb: Event_Callback; tsk: CLTaskBase) :=
|
||||
static procedure __EventList.AttachCallback(ev: cl_event; cb: EventCallback; tsk: CLTaskBase) :=
|
||||
tsk.AddErr( cl.SetEventCallback(ev, CommandExecutionStatus.COMPLETE, cb, __NativUtils.GCHndAlloc(cb)) );
|
||||
|
||||
function __EventList.AttachCallback(cb: Event_Callback; c: Context; var cq: cl_command_queue): cl_event;
|
||||
function __EventList.AttachCallback(cb: EventCallback; c: Context; var cq: cl_command_queue): cl_event;
|
||||
begin
|
||||
|
||||
var ev: cl_event;
|
||||
|
|
@ -1848,7 +1840,7 @@ begin
|
|||
if cq=cl_command_queue.Zero then
|
||||
begin
|
||||
var ec: ErrorCode;
|
||||
cq := cl.CreateCommandQueue(c._context, c._device, CommandQueuePropertyFlags.NONE, ec);
|
||||
cq := cl.CreateCommandQueueWithProperties(c._context,c._device, IntPtr.Zero, ec);
|
||||
ec.RaiseIfError;
|
||||
end;
|
||||
|
||||
|
|
@ -2851,7 +2843,7 @@ type
|
|||
if cq=cl_command_queue.Zero then
|
||||
begin
|
||||
var ec: ErrorCode;
|
||||
cq := cl.CreateCommandQueue(c._context, c._device, CommandQueuePropertyFlags.NONE, ec);
|
||||
cq := cl.CreateCommandQueueWithProperties(c._context,c._device, IntPtr.Zero, ec);
|
||||
ec.RaiseIfError;
|
||||
end;
|
||||
|
||||
|
|
@ -2890,7 +2882,7 @@ type
|
|||
end).Start else
|
||||
begin
|
||||
|
||||
var set_complete: Event_Callback := (ev,st,data)->
|
||||
var set_complete: EventCallback := (ev,st,data)->
|
||||
begin
|
||||
tsk.AddErr( st );
|
||||
|
||||
|
|
@ -2982,7 +2974,7 @@ type
|
|||
var res_ev: cl_event;
|
||||
|
||||
cl.EnqueueWriteBuffer(
|
||||
l_cq, b.memobj, 0,
|
||||
l_cq, b.memobj, Bool.NON_BLOCKING,
|
||||
new UIntPtr(offset.Get), new UIntPtr(len.Get),
|
||||
ptr.Get,
|
||||
prev_ev.count,prev_ev.evs,res_ev
|
||||
|
|
@ -3027,10 +3019,10 @@ type
|
|||
begin
|
||||
|
||||
cl.EnqueueWriteBuffer(
|
||||
l_cq, b.memobj, 1,
|
||||
l_cq, b.memobj, Bool.BLOCKING,
|
||||
new UIntPtr(offset.WaitAndGet), new UIntPtr(len.WaitAndGet),
|
||||
Marshal.UnsafeAddrOfPinnedArrayElement(a.WaitAndGet,0),
|
||||
0,nil,nil
|
||||
0,IntPtr.Zero,IntPtr.Zero
|
||||
).RaiseIfError;
|
||||
|
||||
Result := cl_event.Zero;
|
||||
|
|
@ -3053,7 +3045,7 @@ type
|
|||
|
||||
public constructor(val: T; offset_q: CommandQueue<integer>);
|
||||
begin
|
||||
self.val := new IntPtr(__NativUtils.CopyToUnm(val));
|
||||
self.val := __NativUtils.CopyToUnm(val);
|
||||
self.offset_q := offset_q;
|
||||
end;
|
||||
|
||||
|
|
@ -3069,7 +3061,7 @@ type
|
|||
var res_ev: cl_event;
|
||||
|
||||
cl.EnqueueWriteBuffer(
|
||||
l_cq, b.memobj, 0,
|
||||
l_cq, b.memobj, Bool.NON_BLOCKING,
|
||||
new UIntPtr(offset.Get), new UIntPtr(Marshal.SizeOf&<T>),
|
||||
self.val,
|
||||
prev_ev.count,prev_ev.evs,res_ev
|
||||
|
|
@ -3110,10 +3102,10 @@ type
|
|||
Result := (b, l_c, l_cq, prev_ev)->
|
||||
begin
|
||||
var res_ev: cl_event;
|
||||
var val_ptr := new IntPtr(__NativUtils.CopyToUnm(val.Get()));
|
||||
var val_ptr := __NativUtils.CopyToUnm(val.Get());
|
||||
|
||||
cl.EnqueueWriteBuffer(
|
||||
l_cq, b.memobj, 0,
|
||||
l_cq, b.memobj, Bool.NON_BLOCKING,
|
||||
new UIntPtr(offset.Get), new UIntPtr(Marshal.SizeOf&<T>),
|
||||
val_ptr,
|
||||
prev_ev.count,prev_ev.evs,res_ev
|
||||
|
|
@ -3184,7 +3176,7 @@ type
|
|||
var res_ev: cl_event;
|
||||
|
||||
cl.EnqueueReadBuffer(
|
||||
l_cq, b.memobj, 0,
|
||||
l_cq, b.memobj, Bool.NON_BLOCKING,
|
||||
new UIntPtr(offset.Get), new UIntPtr(len.Get),
|
||||
ptr.Get,
|
||||
prev_ev.count,prev_ev.evs,res_ev
|
||||
|
|
@ -3229,10 +3221,10 @@ type
|
|||
begin
|
||||
|
||||
cl.EnqueueReadBuffer(
|
||||
l_cq, b.memobj, 1,
|
||||
l_cq, b.memobj, Bool.BLOCKING,
|
||||
new UIntPtr(offset.WaitAndGet), new UIntPtr(len.WaitAndGet),
|
||||
Marshal.UnsafeAddrOfPinnedArrayElement(a.WaitAndGet,0),
|
||||
0,nil,nil
|
||||
0,IntPtr.Zero,IntPtr.Zero
|
||||
).RaiseIfError;
|
||||
|
||||
Result := cl_event.Zero;
|
||||
|
|
@ -3346,8 +3338,8 @@ type
|
|||
new UIntPtr(offset.WaitAndGet), new UIntPtr(len.WaitAndGet),
|
||||
prev_ev.count,prev_ev.evs,res_ev
|
||||
).RaiseIfError;
|
||||
cl.WaitForEvents(1,@res_ev);
|
||||
cl.ReleaseEvent(res_ev);
|
||||
cl.WaitForEvents(1,res_ev).RaiseIfError;
|
||||
cl.ReleaseEvent(res_ev).RaiseIfError;
|
||||
|
||||
a_hnd.Free;
|
||||
Result := cl_event.Zero;
|
||||
|
|
@ -3370,7 +3362,7 @@ type
|
|||
|
||||
public constructor(val: T; offset_q, len_q: CommandQueue<integer>);
|
||||
begin
|
||||
self.val := new IntPtr(__NativUtils.CopyToUnm(val));
|
||||
self.val := __NativUtils.CopyToUnm(val);
|
||||
self.offset_q := offset_q;
|
||||
self.len_q := len_q;
|
||||
end;
|
||||
|
|
@ -3432,7 +3424,7 @@ type
|
|||
Result := (b, l_c, l_cq, prev_ev)->
|
||||
begin
|
||||
var res_ev: cl_event;
|
||||
var val_ptr := new IntPtr(__NativUtils.CopyToUnm(val.Get()));
|
||||
var val_ptr := __NativUtils.CopyToUnm(val.Get());
|
||||
|
||||
cl.EnqueueFillBuffer(
|
||||
l_cq, b.memobj,
|
||||
|
|
@ -3704,7 +3696,7 @@ begin
|
|||
if self.memobj<>cl_mem.Zero then Dispose;
|
||||
GC.AddMemoryPressure(Size64);
|
||||
var ec: ErrorCode;
|
||||
self.memobj := cl.CreateBuffer(c._context, MemoryFlags.READ_WRITE, self.sz, IntPtr.Zero, ec);
|
||||
self.memobj := cl.CreateBuffer(c._context, MemFlags.MEM_READ_WRITE, self.sz, IntPtr.Zero, ec);
|
||||
ec.RaiseIfError;
|
||||
end;
|
||||
|
||||
|
|
@ -3720,7 +3712,7 @@ begin
|
|||
new UIntPtr( offset ),
|
||||
new UIntPtr( size )
|
||||
);
|
||||
Result.memobj := cl.CreateSubBuffer(self.memobj, MemoryFlags.READ_WRITE, BufferCreateType.REGION, pointer(@reg), ec);
|
||||
Result.memobj := cl.CreateSubBuffer(self.memobj, MemFlags.MEM_READ_WRITE, BufferCreateType.BUFFER_CREATE_TYPE_REGION,reg, ec);
|
||||
ec.RaiseIfError;
|
||||
|
||||
end;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -252,6 +252,9 @@ type
|
|||
/// Представляет результаты из набора групп при выполнении Regex.Match
|
||||
RegexGroupCollection = System.Text.RegularExpressions.GroupCollection;
|
||||
|
||||
/// Предоставляет методы для точного измерения затраченного времени
|
||||
Stopwatch = System.Diagnostics.Stopwatch;
|
||||
|
||||
/// Представляет тип короткой строки фиксированной длины 255 символов
|
||||
ShortString = string[255];
|
||||
|
||||
|
|
@ -585,6 +588,146 @@ type
|
|||
/// Считывает строку из бестипового файла
|
||||
function ReadString: string;
|
||||
end;
|
||||
|
||||
type
|
||||
/// Тип диапазона целых
|
||||
IntRange = class(IEnumerable<integer>)
|
||||
private
|
||||
l,h: integer;
|
||||
function GetCount: integer;
|
||||
begin
|
||||
Result := h-l+1;
|
||||
if Result<0 then
|
||||
Result := 0;
|
||||
end;
|
||||
public
|
||||
constructor(l,h: integer);
|
||||
begin
|
||||
Self.l := l;
|
||||
Self.h := h;
|
||||
end;
|
||||
property Low: integer read l;
|
||||
property High: integer read h;
|
||||
property Count: integer read GetCount;
|
||||
|
||||
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>;
|
||||
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Self.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;
|
||||
function ToArray: array of integer;
|
||||
begin
|
||||
Result := new integer[Count];
|
||||
var x := l;
|
||||
for var i := 0 to Result.Length - 1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
x += 1;
|
||||
end;
|
||||
end;
|
||||
function ToList: List<integer>;
|
||||
begin
|
||||
Result := new List<integer>;
|
||||
var x := l;
|
||||
loop Count do
|
||||
begin
|
||||
Result.Add(x);
|
||||
x += 1;
|
||||
end;
|
||||
end;
|
||||
function ToLinkedList: LinkedList<integer>;
|
||||
begin
|
||||
Result := new LinkedList<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
function ToHashSet: HashSet<integer>;
|
||||
begin
|
||||
Result := new HashSet<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
function ToSortedSet: SortedSet<integer>;
|
||||
begin
|
||||
Result := new SortedSet<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
end;
|
||||
|
||||
/// Тип диапазона символов
|
||||
CharRange = class(IEnumerable<char>)
|
||||
private
|
||||
l,h: char;
|
||||
function GetCount: integer;
|
||||
begin
|
||||
Result := integer(h) - integer(l)+1;
|
||||
if Result<0 then
|
||||
Result := 0;
|
||||
end;
|
||||
public
|
||||
constructor(l,h: char);
|
||||
begin
|
||||
Self.l := l;
|
||||
Self.h := h;
|
||||
end;
|
||||
property Low: char read l;
|
||||
property High: char read h;
|
||||
property Count: integer read GetCount;
|
||||
|
||||
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>;
|
||||
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := 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;
|
||||
|
||||
function ToArray: array of char;
|
||||
begin
|
||||
Result := new char[Count];
|
||||
var x := l;
|
||||
for var i := 0 to Result.Length - 1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
x := char(integer(x) + 1);
|
||||
end;
|
||||
end;
|
||||
function ToList: List<char>;
|
||||
begin
|
||||
Result := new List<char>;
|
||||
var x := l;
|
||||
loop Count do
|
||||
begin
|
||||
Result.Add(x);
|
||||
x := char(integer(x) + 1);
|
||||
end;
|
||||
end;
|
||||
function ToLinkedList: LinkedList<char>;
|
||||
begin
|
||||
Result := new LinkedList<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
function ToHashSet: HashSet<char>;
|
||||
begin
|
||||
Result := new HashSet<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
function ToSortedSet: SortedSet<char>;
|
||||
begin
|
||||
Result := new SortedSet<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
end;
|
||||
|
||||
//{{{doc: Начало секции интерфейса для документации }}}
|
||||
|
||||
|
|
@ -1965,6 +2108,11 @@ function ReadSeqStringWhile(prompt: string; cond: string->boolean): sequence of
|
|||
function Arr<T>(params a: array of T): array of T;
|
||||
/// Возвращает массив, заполненный значениями из последовательнсти
|
||||
function Arr<T>(a: sequence of T): array of T;
|
||||
/// Возвращает массив, заполненный диапазоном значений
|
||||
function Arr(a: IntRange): array of integer;
|
||||
/// Возвращает массив, заполненный диапазоном значений
|
||||
function Arr(a: CharRange): array of char;
|
||||
|
||||
/// Возвращает массив размера n, заполненный случайными целыми значениями
|
||||
function ArrRandom(n: integer := 10; a: integer := 0; b: integer := 100): array of integer;
|
||||
/// Возвращает массив размера n, заполненный случайными целыми значениями
|
||||
|
|
@ -2054,18 +2202,39 @@ function Rec<T1, T2, T3, T4, T5, T6, T7>(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5;
|
|||
function Lst<T>(params a: array of T): List<T>;
|
||||
/// Возвращает список, заполненный значениями из последовательности
|
||||
function Lst<T>(a: sequence of T): List<T>;
|
||||
/// Возвращает список, заполненный диапазоном значений
|
||||
function Lst(a: IntRange): List<integer>;
|
||||
/// Возвращает список, заполненный диапазоном значений
|
||||
function Lst(a: CharRange): List<char>;
|
||||
|
||||
/// Возвращает двусвязный список, заполненный указанными значениями
|
||||
function LLst<T>(params a: array of T): LinkedList<T>;
|
||||
/// Возвращает двусвязный список, заполненный значениями из последовательности
|
||||
function LLst<T>(a: sequence of T): LinkedList<T>;
|
||||
/// Возвращает двусвязный список, заполненный диапазоном значений
|
||||
function LLst(a: IntRange): LinkedList<integer>;
|
||||
/// Возвращает двусвязный список, заполненный диапазоном значений
|
||||
function LLst(a: CharRange): LinkedList<char>;
|
||||
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное указанными значениями
|
||||
function HSet<T>(params a: array of T): HashSet<T>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное значениями из последовательности
|
||||
function HSet<T>(a: sequence of T): HashSet<T>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное диапазоном значений
|
||||
function HSet(a: IntRange): HashSet<integer>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное заполненный диапазоном значений
|
||||
function HSet(a: CharRange): HashSet<char>;
|
||||
|
||||
/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
|
||||
function SSet<T>(params a: array of T): SortedSet<T>;
|
||||
/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
|
||||
function SSet<T>(a: sequence of T): SortedSet<T>;
|
||||
/// Возвращает множество на базе на базе бинарного дерева поиска, заполненное диапазоном значений
|
||||
function SSet(a: IntRange): SortedSet<integer>;
|
||||
/// Возвращает множество на базе на базе бинарного дерева поиска, заполненное заполненный диапазоном значений
|
||||
function SSet(a: CharRange): SortedSet<char>;
|
||||
|
||||
|
||||
/// Возвращает словарь пар элементов (ключ, значение)
|
||||
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
|
||||
/// Возвращает словарь пар элементов (ключ, значение)
|
||||
|
|
@ -2427,67 +2596,6 @@ 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;
|
||||
///--
|
||||
|
|
@ -3761,6 +3869,10 @@ begin
|
|||
Result := sb.ToString;
|
||||
end;
|
||||
|
||||
function IntRange.GetEnumerator(): IEnumerator<integer> := Range(l,h).GetEnumerator;
|
||||
|
||||
function CharRange.GetEnumerator(): IEnumerator<char> := Range(l,h).GetEnumerator;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Операции для string и char
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -4371,6 +4483,20 @@ begin
|
|||
Result := a.ToArray;
|
||||
end;
|
||||
|
||||
function Arr(a: IntRange): array of integer := a.ToArray;
|
||||
|
||||
function Arr(a: CharRange): array of char;
|
||||
begin
|
||||
var n := integer(a.High) - integer(a.Low) + 1;
|
||||
Result := new char[n];
|
||||
var x := a.Low;
|
||||
for var i := 0 to n-1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
Inc(x)
|
||||
end;
|
||||
end;
|
||||
|
||||
function Seq<T>(params a: array of T): sequence of T;
|
||||
begin
|
||||
var res := new T[a.Length];
|
||||
|
|
@ -4681,45 +4807,39 @@ function Rec<T1, T2, T3, T4, T5, T6, T7>(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5;
|
|||
// -----------------------------------------------------------------------------
|
||||
// Функции Lst, LLst, Dict, KV, HSet, SSet
|
||||
// -----------------------------------------------------------------------------
|
||||
function Lst<T>(params a: array of T): List<T>;
|
||||
begin
|
||||
Result := new List<T>(a);
|
||||
end;
|
||||
function Lst<T>(params a: array of T): List<T> := new List<T>(a);
|
||||
|
||||
function Lst<T>(a: sequence of T): List<T>;
|
||||
begin
|
||||
Result := new List<T>(a);
|
||||
end;
|
||||
function Lst<T>(a: sequence of T): List<T> := new List<T>(a);
|
||||
|
||||
function LLst<T>(params a: array of T): LinkedList<T>;
|
||||
begin
|
||||
Result := new LinkedList<T>(a);
|
||||
end;
|
||||
function Lst(a: IntRange): List<integer> := a.ToList;
|
||||
|
||||
function LLst<T>(a: sequence of T): LinkedList<T>;
|
||||
begin
|
||||
Result := new LinkedList<T>(a);
|
||||
end;
|
||||
function Lst(a: CharRange): List<char> := a.ToList;
|
||||
|
||||
function HSet<T>(params a: array of T): HashSet<T>;
|
||||
begin
|
||||
Result := new HashSet<T>(a);
|
||||
end;
|
||||
function LLst<T>(params a: array of T): LinkedList<T> := new LinkedList<T>(a);
|
||||
|
||||
function SSet<T>(params a: array of T): SortedSet<T>;
|
||||
begin
|
||||
Result := new SortedSet<T>(a);
|
||||
end;
|
||||
function LLst<T>(a: sequence of T): LinkedList<T> := new LinkedList<T>(a);
|
||||
|
||||
function HSet<T>(a: sequence of T): HashSet<T>;
|
||||
begin
|
||||
Result := new HashSet<T>(a);
|
||||
end;
|
||||
function LLst(a: IntRange): LinkedList<integer> := a.ToLinkedList;
|
||||
|
||||
function LLst(a: CharRange): LinkedList<char> := a.ToLinkedList;
|
||||
|
||||
|
||||
function HSet<T>(params a: array of T): HashSet<T> := new HashSet<T>(a);
|
||||
|
||||
function SSet<T>(params a: array of T): SortedSet<T> := new SortedSet<T>(a);
|
||||
|
||||
function HSet<T>(a: sequence of T): HashSet<T> := new HashSet<T>(a);
|
||||
|
||||
function SSet<T>(a: sequence of T): SortedSet<T> := new SortedSet<T>(a);
|
||||
|
||||
function HSet(a: IntRange): HashSet<integer> := a.ToHashSet&<integer>;
|
||||
|
||||
function HSet(a: CharRange): HashSet<char> := a.ToHashSet&<char>;
|
||||
|
||||
function SSet(a: IntRange): SortedSet<integer> := a.ToSortedSet;
|
||||
|
||||
function SSet(a: CharRange): SortedSet<char> := a.ToSortedSet;
|
||||
|
||||
function SSet<T>(a: sequence of T): SortedSet<T>;
|
||||
begin
|
||||
Result := new SortedSet<T>(a);
|
||||
end;
|
||||
|
||||
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
|
||||
begin
|
||||
|
|
@ -9065,84 +9185,98 @@ type
|
|||
//------------------------------------------------------------------------------
|
||||
//>> Метод расширения Print для элементарных типов # Print for elementary types
|
||||
//------------------------------------------------------------------------------
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: integer): integer; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: int64): int64; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: real): real; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: char): char; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: boolean): boolean; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: BigInteger): BigInteger; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: string): string; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: integer): integer; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: int64): int64; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: real): real; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: char): char; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: boolean): boolean; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: BigInteger): BigInteger; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: string): string; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
|
|
|
|||
25
TestSuite/errors/err0348_ur.pas
Normal file
25
TestSuite/errors/err0348_ur.pas
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: integer := cc;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int := global {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
25
TestSuite/errors/err0349_ur.pas
Normal file
25
TestSuite/errors/err0349_ur.pas
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: integer := classfield;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int := global {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
25
TestSuite/errors/err0350_ur.pas
Normal file
25
TestSuite/errors/err0350_ur.pas
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: T;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int := global {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
25
TestSuite/errors/err0351_ur.pas
Normal file
25
TestSuite/errors/err0351_ur.pas
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: integer := pa;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int := global {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
25
TestSuite/errors/err0352_ur.pas
Normal file
25
TestSuite/errors/err0352_ur.pas
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: integer := 1;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int1 := 1 {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
26
TestSuite/ur1.pas
Normal file
26
TestSuite/ur1.pas
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
var global: integer;
|
||||
|
||||
type int = integer;
|
||||
|
||||
type Class1<T,T1> = class
|
||||
classfield: integer;
|
||||
const cc = 2;
|
||||
function p<PPT>(pa,pb: real): integer;
|
||||
type int1 = integer;
|
||||
var
|
||||
A: record
|
||||
i: array of integer := nil{cc {classfield};
|
||||
jlocal1: record
|
||||
j: integer;
|
||||
mostinternal1: set of integer := [j];
|
||||
end;
|
||||
klocal1: int := global {* classfield};
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Assert(True);
|
||||
end.
|
||||
17
TestSuite/ur2.pas
Normal file
17
TestSuite/ur2.pas
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
type Class1<T,T1> = class
|
||||
procedure p;
|
||||
var
|
||||
A: record
|
||||
i: integer;
|
||||
jlocal0: record
|
||||
i: real;
|
||||
end;
|
||||
end;
|
||||
begin
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Assert(True)
|
||||
end.
|
||||
|
|
@ -3579,7 +3579,8 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
if (_class_definition.keyword == class_keyword.Record && _class_definition.Parent is var_def_statement) // безымянная запись
|
||||
{
|
||||
if (_class_definition.class_parents != null && _class_definition.class_parents.Count>0)
|
||||
// SSM 27.02.12 - всё это перенес в синтаксический визитор UnnamedRecordsCheckVisitor
|
||||
/*if (_class_definition.class_parents != null && _class_definition.class_parents.Count>0)
|
||||
AddError(new SimpleSemanticError(get_location(_class_definition), "UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE"));
|
||||
var pds = _class_definition.DescendantNodes().OfType<procedure_definition>();
|
||||
if (pds.Count() > 0)
|
||||
|
|
@ -3589,9 +3590,9 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (sps.Count() > 0)
|
||||
AddError(new SimpleSemanticError(get_location(sps.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES"));
|
||||
|
||||
/*var cds = _class_definition.DescendantNodes().OfType<constructor>();
|
||||
var cds = _class_definition.DescendantNodes().OfType<constructor>();
|
||||
if (cds.Count() > 0)
|
||||
AddError(new SimpleSemanticError(get_location(cds.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS"));*/
|
||||
AddError(new SimpleSemanticError(get_location(cds.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS"));
|
||||
if (_class_definition.body.class_def_blocks.First().access_mod.access_level != access_modifer.public_modifer)
|
||||
{
|
||||
var f = _class_definition.body.class_def_blocks.First();
|
||||
|
|
@ -3608,9 +3609,9 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (loc == null)
|
||||
loc = get_location(_class_definition);
|
||||
AddError(new SimpleSemanticError(loc, "UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS"));
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
if (_class_definition.attribute != class_attribute.None && _class_definition.body == null)
|
||||
AddError(new SimpleSemanticError(get_location(_class_definition), "CLASS_ATTRIBUTE_NOT_ALLOWED_IN_CLASS_PREDEFINTIONS"));
|
||||
|
|
@ -12704,7 +12705,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
: null;
|
||||
if (_procedure_definition.proc_header.attributes != null && context.converted_func_stack.size >= 1)
|
||||
AddError(get_location(_procedure_definition.proc_header), "ATTRIBUTES_FOR_NESTED_FUNCTIONS_NOT_ALLOWED");
|
||||
if (context.top_function != null && context.top_function.generic_params != null && !LambdaHelper.IsLambdaName(proc_name))
|
||||
if (context.top_function != null && context.top_function.generic_params != null && !LambdaHelper.IsLambdaName(proc_name) && !(_procedure_definition.proc_header is SyntaxTree.constructor))
|
||||
AddError(get_location(_procedure_definition.proc_header), "NESTED_FUNCTIONS_IN_GENERIC_FUNCTIONS_NOT_ALLOWED");
|
||||
if (context.top_function != null && _procedure_definition.proc_header.template_args != null && !LambdaHelper.IsLambdaName(proc_name))
|
||||
AddError(get_location(_procedure_definition.proc_header), "GENERIC_NESTED_FUNCTIONS_NOT_ALLOWED");
|
||||
|
|
|
|||
|
|
@ -252,6 +252,9 @@ type
|
|||
/// Представляет результаты из набора групп при выполнении Regex.Match
|
||||
RegexGroupCollection = System.Text.RegularExpressions.GroupCollection;
|
||||
|
||||
/// Предоставляет методы для точного измерения затраченного времени
|
||||
Stopwatch = System.Diagnostics.Stopwatch;
|
||||
|
||||
/// Представляет тип короткой строки фиксированной длины 255 символов
|
||||
ShortString = string[255];
|
||||
|
||||
|
|
@ -585,6 +588,146 @@ type
|
|||
/// Считывает строку из бестипового файла
|
||||
function ReadString: string;
|
||||
end;
|
||||
|
||||
type
|
||||
/// Тип диапазона целых
|
||||
IntRange = class(IEnumerable<integer>)
|
||||
private
|
||||
l,h: integer;
|
||||
function GetCount: integer;
|
||||
begin
|
||||
Result := h-l+1;
|
||||
if Result<0 then
|
||||
Result := 0;
|
||||
end;
|
||||
public
|
||||
constructor(l,h: integer);
|
||||
begin
|
||||
Self.l := l;
|
||||
Self.h := h;
|
||||
end;
|
||||
property Low: integer read l;
|
||||
property High: integer read h;
|
||||
property Count: integer read GetCount;
|
||||
|
||||
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>;
|
||||
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Self.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;
|
||||
function ToArray: array of integer;
|
||||
begin
|
||||
Result := new integer[Count];
|
||||
var x := l;
|
||||
for var i := 0 to Result.Length - 1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
x += 1;
|
||||
end;
|
||||
end;
|
||||
function ToList: List<integer>;
|
||||
begin
|
||||
Result := new List<integer>;
|
||||
var x := l;
|
||||
loop Count do
|
||||
begin
|
||||
Result.Add(x);
|
||||
x += 1;
|
||||
end;
|
||||
end;
|
||||
function ToLinkedList: LinkedList<integer>;
|
||||
begin
|
||||
Result := new LinkedList<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
function ToHashSet: HashSet<integer>;
|
||||
begin
|
||||
Result := new HashSet<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
function ToSortedSet: SortedSet<integer>;
|
||||
begin
|
||||
Result := new SortedSet<integer>(System.Linq.Enumerable.Range(l,Count));
|
||||
end;
|
||||
end;
|
||||
|
||||
/// Тип диапазона символов
|
||||
CharRange = class(IEnumerable<char>)
|
||||
private
|
||||
l,h: char;
|
||||
function GetCount: integer;
|
||||
begin
|
||||
Result := integer(h) - integer(l)+1;
|
||||
if Result<0 then
|
||||
Result := 0;
|
||||
end;
|
||||
public
|
||||
constructor(l,h: char);
|
||||
begin
|
||||
Self.l := l;
|
||||
Self.h := h;
|
||||
end;
|
||||
property Low: char read l;
|
||||
property High: char read h;
|
||||
property Count: integer read GetCount;
|
||||
|
||||
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>;
|
||||
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := 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;
|
||||
|
||||
function ToArray: array of char;
|
||||
begin
|
||||
Result := new char[Count];
|
||||
var x := l;
|
||||
for var i := 0 to Result.Length - 1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
x := char(integer(x) + 1);
|
||||
end;
|
||||
end;
|
||||
function ToList: List<char>;
|
||||
begin
|
||||
Result := new List<char>;
|
||||
var x := l;
|
||||
loop Count do
|
||||
begin
|
||||
Result.Add(x);
|
||||
x := char(integer(x) + 1);
|
||||
end;
|
||||
end;
|
||||
function ToLinkedList: LinkedList<char>;
|
||||
begin
|
||||
Result := new LinkedList<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
function ToHashSet: HashSet<char>;
|
||||
begin
|
||||
Result := new HashSet<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
function ToSortedSet: SortedSet<char>;
|
||||
begin
|
||||
Result := new SortedSet<char>(System.Linq.Enumerable.Range(integer(l),Count).Select(i -> char(i)));
|
||||
end;
|
||||
end;
|
||||
|
||||
//{{{doc: Начало секции интерфейса для документации }}}
|
||||
|
||||
|
|
@ -1965,6 +2108,11 @@ function ReadSeqStringWhile(prompt: string; cond: string->boolean): sequence of
|
|||
function Arr<T>(params a: array of T): array of T;
|
||||
/// Возвращает массив, заполненный значениями из последовательнсти
|
||||
function Arr<T>(a: sequence of T): array of T;
|
||||
/// Возвращает массив, заполненный диапазоном значений
|
||||
function Arr(a: IntRange): array of integer;
|
||||
/// Возвращает массив, заполненный диапазоном значений
|
||||
function Arr(a: CharRange): array of char;
|
||||
|
||||
/// Возвращает массив размера n, заполненный случайными целыми значениями
|
||||
function ArrRandom(n: integer := 10; a: integer := 0; b: integer := 100): array of integer;
|
||||
/// Возвращает массив размера n, заполненный случайными целыми значениями
|
||||
|
|
@ -2054,18 +2202,39 @@ function Rec<T1, T2, T3, T4, T5, T6, T7>(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5;
|
|||
function Lst<T>(params a: array of T): List<T>;
|
||||
/// Возвращает список, заполненный значениями из последовательности
|
||||
function Lst<T>(a: sequence of T): List<T>;
|
||||
/// Возвращает список, заполненный диапазоном значений
|
||||
function Lst(a: IntRange): List<integer>;
|
||||
/// Возвращает список, заполненный диапазоном значений
|
||||
function Lst(a: CharRange): List<char>;
|
||||
|
||||
/// Возвращает двусвязный список, заполненный указанными значениями
|
||||
function LLst<T>(params a: array of T): LinkedList<T>;
|
||||
/// Возвращает двусвязный список, заполненный значениями из последовательности
|
||||
function LLst<T>(a: sequence of T): LinkedList<T>;
|
||||
/// Возвращает двусвязный список, заполненный диапазоном значений
|
||||
function LLst(a: IntRange): LinkedList<integer>;
|
||||
/// Возвращает двусвязный список, заполненный диапазоном значений
|
||||
function LLst(a: CharRange): LinkedList<char>;
|
||||
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное указанными значениями
|
||||
function HSet<T>(params a: array of T): HashSet<T>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное значениями из последовательности
|
||||
function HSet<T>(a: sequence of T): HashSet<T>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное диапазоном значений
|
||||
function HSet(a: IntRange): HashSet<integer>;
|
||||
/// Возвращает множество на базе хеш таблицы, заполненное заполненный диапазоном значений
|
||||
function HSet(a: CharRange): HashSet<char>;
|
||||
|
||||
/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
|
||||
function SSet<T>(params a: array of T): SortedSet<T>;
|
||||
/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
|
||||
function SSet<T>(a: sequence of T): SortedSet<T>;
|
||||
/// Возвращает множество на базе на базе бинарного дерева поиска, заполненное диапазоном значений
|
||||
function SSet(a: IntRange): SortedSet<integer>;
|
||||
/// Возвращает множество на базе на базе бинарного дерева поиска, заполненное заполненный диапазоном значений
|
||||
function SSet(a: CharRange): SortedSet<char>;
|
||||
|
||||
|
||||
/// Возвращает словарь пар элементов (ключ, значение)
|
||||
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
|
||||
/// Возвращает словарь пар элементов (ключ, значение)
|
||||
|
|
@ -2427,67 +2596,6 @@ 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;
|
||||
///--
|
||||
|
|
@ -3761,6 +3869,10 @@ begin
|
|||
Result := sb.ToString;
|
||||
end;
|
||||
|
||||
function IntRange.GetEnumerator(): IEnumerator<integer> := Range(l,h).GetEnumerator;
|
||||
|
||||
function CharRange.GetEnumerator(): IEnumerator<char> := Range(l,h).GetEnumerator;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Операции для string и char
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -4371,6 +4483,20 @@ begin
|
|||
Result := a.ToArray;
|
||||
end;
|
||||
|
||||
function Arr(a: IntRange): array of integer := a.ToArray;
|
||||
|
||||
function Arr(a: CharRange): array of char;
|
||||
begin
|
||||
var n := integer(a.High) - integer(a.Low) + 1;
|
||||
Result := new char[n];
|
||||
var x := a.Low;
|
||||
for var i := 0 to n-1 do
|
||||
begin
|
||||
Result[i] := x;
|
||||
Inc(x)
|
||||
end;
|
||||
end;
|
||||
|
||||
function Seq<T>(params a: array of T): sequence of T;
|
||||
begin
|
||||
var res := new T[a.Length];
|
||||
|
|
@ -4681,45 +4807,39 @@ function Rec<T1, T2, T3, T4, T5, T6, T7>(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5;
|
|||
// -----------------------------------------------------------------------------
|
||||
// Функции Lst, LLst, Dict, KV, HSet, SSet
|
||||
// -----------------------------------------------------------------------------
|
||||
function Lst<T>(params a: array of T): List<T>;
|
||||
begin
|
||||
Result := new List<T>(a);
|
||||
end;
|
||||
function Lst<T>(params a: array of T): List<T> := new List<T>(a);
|
||||
|
||||
function Lst<T>(a: sequence of T): List<T>;
|
||||
begin
|
||||
Result := new List<T>(a);
|
||||
end;
|
||||
function Lst<T>(a: sequence of T): List<T> := new List<T>(a);
|
||||
|
||||
function LLst<T>(params a: array of T): LinkedList<T>;
|
||||
begin
|
||||
Result := new LinkedList<T>(a);
|
||||
end;
|
||||
function Lst(a: IntRange): List<integer> := a.ToList;
|
||||
|
||||
function LLst<T>(a: sequence of T): LinkedList<T>;
|
||||
begin
|
||||
Result := new LinkedList<T>(a);
|
||||
end;
|
||||
function Lst(a: CharRange): List<char> := a.ToList;
|
||||
|
||||
function HSet<T>(params a: array of T): HashSet<T>;
|
||||
begin
|
||||
Result := new HashSet<T>(a);
|
||||
end;
|
||||
function LLst<T>(params a: array of T): LinkedList<T> := new LinkedList<T>(a);
|
||||
|
||||
function SSet<T>(params a: array of T): SortedSet<T>;
|
||||
begin
|
||||
Result := new SortedSet<T>(a);
|
||||
end;
|
||||
function LLst<T>(a: sequence of T): LinkedList<T> := new LinkedList<T>(a);
|
||||
|
||||
function HSet<T>(a: sequence of T): HashSet<T>;
|
||||
begin
|
||||
Result := new HashSet<T>(a);
|
||||
end;
|
||||
function LLst(a: IntRange): LinkedList<integer> := a.ToLinkedList;
|
||||
|
||||
function LLst(a: CharRange): LinkedList<char> := a.ToLinkedList;
|
||||
|
||||
|
||||
function HSet<T>(params a: array of T): HashSet<T> := new HashSet<T>(a);
|
||||
|
||||
function SSet<T>(params a: array of T): SortedSet<T> := new SortedSet<T>(a);
|
||||
|
||||
function HSet<T>(a: sequence of T): HashSet<T> := new HashSet<T>(a);
|
||||
|
||||
function SSet<T>(a: sequence of T): SortedSet<T> := new SortedSet<T>(a);
|
||||
|
||||
function HSet(a: IntRange): HashSet<integer> := a.ToHashSet&<integer>;
|
||||
|
||||
function HSet(a: CharRange): HashSet<char> := a.ToHashSet&<char>;
|
||||
|
||||
function SSet(a: IntRange): SortedSet<integer> := a.ToSortedSet;
|
||||
|
||||
function SSet(a: CharRange): SortedSet<char> := a.ToSortedSet;
|
||||
|
||||
function SSet<T>(a: sequence of T): SortedSet<T>;
|
||||
begin
|
||||
Result := new SortedSet<T>(a);
|
||||
end;
|
||||
|
||||
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
|
||||
begin
|
||||
|
|
@ -9065,84 +9185,98 @@ type
|
|||
//------------------------------------------------------------------------------
|
||||
//>> Метод расширения Print для элементарных типов # Print for elementary types
|
||||
//------------------------------------------------------------------------------
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: integer): integer; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: int64): int64; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: real): real; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: char): char; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: boolean): boolean; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: BigInteger): BigInteger; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран, после чего выводит пробел
|
||||
function Print(Self: string): string; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Print(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: integer): integer; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: int64): int64; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: real): real; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: char): char; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: boolean): boolean; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: BigInteger): BigInteger; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
/// Выводит значение на экран и переходит на новую строку
|
||||
function Println(Self: string): string; extensionmethod;
|
||||
begin
|
||||
PABCSystem.Println(Self);
|
||||
|
|
|
|||
|
|
@ -21,4 +21,15 @@ ONLY_ONE_DECONSTRUCT_ALLOWED=Only one user deconstructor is allowed
|
|||
|
||||
Var_{0}_is_already_defined=Variable {0} is already defined
|
||||
|
||||
?._CANNOT_BE_IN_THIS_CONTEXT=Operator ?. cannot be in this context
|
||||
?._CANNOT_BE_IN_THIS_CONTEXT=Operator ?. cannot be in this context
|
||||
|
||||
INVALID_INTERFACE_MEMBER=Interfaces cannot contain fields and method implementation
|
||||
INDEXED_AUTO_PROPERTY=Autoproperties cannot be indexed properties
|
||||
|
||||
UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Unnamed records can not implement interfaces
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_METHODS=Unnamed records can not contain methods
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Unnamed records can not contain properties
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Unnamed records can not contain constructors
|
||||
UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Unnamed records can contain only one section with public visibility
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Unnamed records can not contain several visibility section
|
||||
UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Unnamed records cannot catch names from nonglobal context
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ IMPOSSIBLE_TO_INFER_SET_TYPE=Нельзя вычислить тип множес
|
|||
BAD_DIAPASON_IN_SET_TYPE=Границы диапазона в константе-множестве должны иметь один тип
|
||||
UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Безымянные записи не могут реализовывать интерфейсы
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_METHODS=Безымянные записи не могут содержать методы
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Безымянные записи не могут содержать методы
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Безымянные записи не могут содержать свойства
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Безымянные записи не могут содержать конструкторы
|
||||
UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Безымянные записи могут содержать лишь одну секцию с public-видимостью
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Безымянные записи не могут содержать несколько секций видимости
|
||||
|
|
|
|||
|
|
@ -27,4 +27,12 @@ Var_{0}_is_already_defined=Переменная {0} уже определена
|
|||
?._CANNOT_BE_IN_THIS_CONTEXT=Операция ?. не может располагаться в этом контексте
|
||||
|
||||
INVALID_INTERFACE_MEMBER=Интерфейсы не могут содержать поля и реализацию методов
|
||||
INDEXED_AUTO_PROPERTY=Автосвойства не могут быть индексными
|
||||
INDEXED_AUTO_PROPERTY=Автосвойства не могут быть индексными
|
||||
|
||||
UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE=Безымянные записи не могут реализовывать интерфейсы
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_METHODS=Безымянные записи не могут содержать методы
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES=Безымянные записи не могут содержать свойства
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS=Безымянные записи не могут содержать конструкторы
|
||||
UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION=Безымянные записи могут содержать лишь одну секцию с public-видимостью
|
||||
UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS=Безымянные записи не могут содержать несколько секций видимости
|
||||
UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT=Безымянные записи не могут захватывать имена из неглобального контекста
|
||||
|
|
|
|||
Loading…
Reference in a new issue