From 3f42c445ce7c7b5bf3d0c38076a40c603de4ccfa Mon Sep 17 00:00:00 2001 From: Vladislav Pichugin Date: Mon, 21 Jun 2021 02:14:05 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20(#251,=20#322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autotests/@refal-5-lambda-diagnostics.ini | 2 +- autotests/opt-tree-spec10.ref | 16 ++ autotests/opt-tree-spec11.ref | 15 + autotests/opt-tree-spec12.ref | 30 ++ autotests/opt-tree-spec7.ref | 12 + autotests/opt-tree-spec8.ref | 15 + autotests/opt-tree-spec9.ref | 12 + .../@refal-5-lambda-diagnostics.ini | 2 +- src/compiler/GenericMatch.ref | 73 ++++- src/compiler/OptTree-Spec.ref | 267 +++++++++--------- 10 files changed, 292 insertions(+), 152 deletions(-) create mode 100644 autotests/opt-tree-spec10.ref create mode 100644 autotests/opt-tree-spec11.ref create mode 100644 autotests/opt-tree-spec12.ref create mode 100644 autotests/opt-tree-spec7.ref create mode 100644 autotests/opt-tree-spec8.ref create mode 100644 autotests/opt-tree-spec9.ref diff --git a/autotests/@refal-5-lambda-diagnostics.ini b/autotests/@refal-5-lambda-diagnostics.ini index 9000025b..161a516f 100644 --- a/autotests/@refal-5-lambda-diagnostics.ini +++ b/autotests/@refal-5-lambda-diagnostics.ini @@ -1,4 +1,4 @@ memory-limit = 10000000 -step-limit = 15000000 +step-limit = 1000000000 idents-limit = 5000 enable-debugger = false diff --git a/autotests/opt-tree-spec10.ref b/autotests/opt-tree-spec10.ref new file mode 100644 index 00000000..74265b75 --- /dev/null +++ b/autotests/opt-tree-spec10.ref @@ -0,0 +1,16 @@ +* TREE + +$ENTRY Go { + = +} + +F { + t.X = +} + +$SPEC Eq e.arg; + +Eq { + t.Eq t.Eq = True; + t._ t._ = False; +} diff --git a/autotests/opt-tree-spec11.ref b/autotests/opt-tree-spec11.ref new file mode 100644 index 00000000..537d6e1f --- /dev/null +++ b/autotests/opt-tree-spec11.ref @@ -0,0 +1,15 @@ +* TREE + +$ENTRY Go { + = +} + +F { + e.X = +} + +$SPEC G e.arg; + +G { + (e.A '@' e.B) s.R (e.C '#' e.D) = (e.A) s.R (e.B) s.R (e.C) s.R (e.D); +} diff --git a/autotests/opt-tree-spec12.ref b/autotests/opt-tree-spec12.ref new file mode 100644 index 00000000..529ec13a --- /dev/null +++ b/autotests/opt-tree-spec12.ref @@ -0,0 +1,30 @@ +* TREE + +$ENTRY Go { + /* empty */ + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = : ('AA') ('BB') ('CC') ('DD') + = /* empty */; +} + +F { + (e.1) (e.2) = ; +} + +$SPEC S e.arg; + +S { + e.A e.B e.A e.C 9 e.D + , e.A : s._ s._ + = (e.A) (e.B) (e.C) (e.D); +} diff --git a/autotests/opt-tree-spec7.ref b/autotests/opt-tree-spec7.ref new file mode 100644 index 00000000..a786632f --- /dev/null +++ b/autotests/opt-tree-spec7.ref @@ -0,0 +1,12 @@ +* TREE + +$ENTRY Go { + e.X = : False = /* empty */; +} + +$SPEC S s.X; + +S { + s.X, A : s.X = True; + s._ = False; +} diff --git a/autotests/opt-tree-spec8.ref b/autotests/opt-tree-spec8.ref new file mode 100644 index 00000000..b0c699a8 --- /dev/null +++ b/autotests/opt-tree-spec8.ref @@ -0,0 +1,15 @@ +* TREE + +$SPEC Rot e.dyn; + +Rot { + e.1 s.2 = s.2 e.1; +} + +Example { + (e.X) (e.Y) = ; +} + +$ENTRY Go { + = ; +} diff --git a/autotests/opt-tree-spec9.ref b/autotests/opt-tree-spec9.ref new file mode 100644 index 00000000..fc62bcb3 --- /dev/null +++ b/autotests/opt-tree-spec9.ref @@ -0,0 +1,12 @@ +* TREE + +$ENTRY Go { + e.X = ; +} + +$SPEC Eq e.arg; + +Eq { + t.X t.X = True t.X; + t.Y t.Z = False t.Y t.Z; +} diff --git a/autotests/positive-random-test/@refal-5-lambda-diagnostics.ini b/autotests/positive-random-test/@refal-5-lambda-diagnostics.ini index 99a2c5f7..161a516f 100644 --- a/autotests/positive-random-test/@refal-5-lambda-diagnostics.ini +++ b/autotests/positive-random-test/@refal-5-lambda-diagnostics.ini @@ -1,4 +1,4 @@ memory-limit = 10000000 -step-limit = 800000000 +step-limit = 1000000000 idents-limit = 5000 enable-debugger = false diff --git a/src/compiler/GenericMatch.ref b/src/compiler/GenericMatch.ref index f1441e0f..ea475de4 100644 --- a/src/compiler/GenericMatch.ref +++ b/src/compiler/GenericMatch.ref @@ -109,7 +109,7 @@ Solve-Spec-Aux { : { e.Begin Generalize (e.Intervals) e.End = (e.L) (e.GenAssigns) > : (e.UsedVars^) (e.L^) (e.GenAssigns^) @@ -127,6 +127,52 @@ Solve-Spec-Aux { } } +/* + Объединяет два интервала, если они пересекаются. + В остальных случаях возвращает исходный список интервалов. + + == (e.Intervals^) + + e.Intervals ::= t.Interval+ + t.Interval ::= ('{' s.BeginCoord s.EndCoord '}') +*/ + +UnionIfIntersect { + (t.Interval-1 t.Interval-2) + , : True + = t.Interval-1 : ('{' s.A s.B '}') + = t.Interval-2 : ('{' s.C s.D '}') + = : s.Min + = : s.Max + = (('{' s.Min s.Max '}')); + + t.Intervals = t.Intervals; +} + +HasIntersection { + (('{' s.A s.B '}') ('{' s.C s.D '}')) + , : '+' + = False; + + (('{' s.A s.B '}') ('{' s.C s.D '}')) + , : '+' + = False; + + t.Intervals = True; +} + +GetExtremum { + s.Extremum s.Sign (s.CurrentCoord e.Rest) + , : s.Sign + = ; + + s.Extremum s.Sign (s.CurrentCoord e.Rest) + = ; + + s.Extremum s.Sign (/* пусто */) + = s.Extremum; +} + /* Преобразует решения в нужный формат для Solve-Drive и Solve-Spec @@ -255,10 +301,10 @@ ApplyAssignments-toExpr { } ApplyAssignment-toExpr { - (e.Val ':' t.Var) e.Begin t.Var e.End - = + (e.Val ':' (s.Type e.Index)) e.Begin (Var s.Type e.Index) e.End + = e.Val - ; + ; t.Assign e.Begin (Brackets e.E) e.End = @@ -2475,18 +2521,15 @@ AddContraction { AddContraction-Spec { t.toAdd (s.OpenFlag e.Contrs) e.Clashes (e.Assigns) - , t.toAdd : ((Var 'e' e._) ':' (Var 'e' e._) (Var 'e' e._)) - = - t.toAdd - ) - - () - >; + = t.toAdd + : { + ((Var 'e' e._) ':' (Var 'e' e._) (Var 'e' e._)) = AfterOpen; - t.toAdd (s.OpenFlag e.Contrs) e.Clashes (e.Assigns) + ((Var 'e' e._) ':' (Var 'e' e._) (Var 't' e._) (Var 'e' e._)) = AfterOpen; + + t._ = s.OpenFlag; + } + : s.OpenFlag^ = ':' - ' [' ']\n'; + ' [' ']\n'; } e.History > > } -PrintSignature { - /* пусто */ = /* пусто */; - t.First e.Last - = - } e.Last> -} - -PrintSignatureItem { - (e.Expr) = ; -} - SpecUnit { (e.SpecInfo (e.Histories-B (t.Name e.History) e.Histories-E) (e.NewFunctions) @@ -930,24 +919,24 @@ Spec-FindInSignatures { /** */ -*IsTrivialSubstitutions { -* e.StaticMatches -* = ; -*} +IsTrivialSubstitutions { + e.StaticMatches + = ; +} *PrepareArgOrPattern { * (e.StaticMatches) (e.DynamicMatches) e.SpecPattern @@ -1286,27 +1275,27 @@ SourceNameOfInstance { * = e.Signature; *} -*NameSignatureVars-Expr { -* t.State e.Expr = ; -*} +NameSignatureVars-Expr { + t.State e.Expr = ; +} -*NameSignatureVars-Term { -* (e.KnownVars) (Var s.Mode) -* = : (e.KnownVars^) e.Index -* = (e.KnownVars) -* (Var e.Index); -* -* t.State (s.BracketsTag e.Expr) -* , : True -* = : t.State^ e.Expr^ -* = t.State (s.BracketsTag e.Expr); -* -* t.State (ADT-Brackets (e.Name) e.Expr) -* = : t.State^ e.Expr^ -* = t.State (ADT-Brackets (e.Name) e.Expr); -* -* t.State t.OtherTerm = t.State t.OtherTerm; -*} +NameSignatureVars-Term { + (e.KnownVars) (Var s.Mode) + = : (e.KnownVars^) e.Index + = (e.KnownVars) + (Var e.Index); + + t.State (s.BracketsTag e.Expr) + , : True + = : t.State^ e.Expr^ + = t.State (s.BracketsTag e.Expr); + + t.State (ADT-Brackets (e.Name) e.Expr) + = : t.State^ e.Expr^ + = t.State (ADT-Brackets (e.Name) e.Expr); + + t.State t.OtherTerm = t.State t.OtherTerm; +} /* Получает обобщённую сигнатуру для двух сигнатур. @@ -1373,91 +1362,68 @@ SourceNameOfInstance { Новая реализация специализации */ -/* TODO: документация функций */ +/** + + == ((e.SpecPattern) (e.Body) s.NextNumber e.Signatures t.NewSignature) + t.NewCall t.NewFunction (e.NewHistory) + + Функция пытается выполнить специализацию для заданного вызова: + # ищет среди сигнатур готовых специализированных функций похожую + * если сигнатура найдена, заменяем исходный вызов на вызов найденной функции + * если сигнатура не найдена выполняем специализацию для аргументов вызова + # формируем новый вызов + # формируем определение новой специализированной функции + # возвращает e.Info с новой сигнатурой, + новый вызов + определение новой специализированной функции +*/ SpecCall { (e.Name) (e.SpecPattern) (e.Body) s.NextNumber e.Signatures (e.Argument) (e.History) - /* - Приводим аргумент к пассивному виду и переименовываем - переменные в теле функции, чтобы они не пересекались с - переменными в аргументе - */ = : e.UsedVars = - : (e.Sg (e.UsedVars^)) e.NewArgument - = : e.Body^ + : (e.ExtractedCalls (e.UsedVars^)) e.NewArgument /* ищем динамическое обобщение для аргумента и образцов */ = - : (e.NewArgument^) (e.Sg^) (e.Solutions) + : (e.NewArgument^) (e.Sg) (e.Solutions) = ; } -RenameVars-Sentences { - (e.KnownVars) ((e.Pattern) e.Tail) e.Sentences - = ( - () - - ) - ; - - (e.KnownVars) /* пусто */ = /* пусто */; -} - -RenameVars-Tail { - (e.KnownVars) (Condition (e.ConditionName) (e.Result) (e.Pattern)) e.Tail - = ( - Condition (e.ConditionName) - () - () - ) - ; - - (e.KnownVars) (e.Result) = (); -} - -RenameVars-Expr { - (e.KnownVars) (Var e.ModeIndex) e.Terms - = : (e.KnownVars^) e.New - = (Var e.New) ; - - (e.KnownVars) (s.BracketsTag e.Inner) e.Terms - , : True - = (s.BracketsTag ) - ; - - (e.KnownVars) (ADT-Brackets (e.Name) e.Inner) e.Terms - = (ADT-Brackets (e.Name) ) - ; - - (e.KnownVars) t.Other e.Terms - = t.Other ; - - (e.KnownVars) /* пусто */ = /* пусто */; -} - DynGenArg { (e.Arg) (e.Sg) (e.Sol) (e.Begin) ((e.Pat) e.Tail) e.Sentences - = : e.UsedVars + = : e.UsedVars + = : (e.UsedVars^) e.eNew + = e.Arg (Brackets (Var e.eNew)) : e.Arg^ + = : e.WrappedCondVars + = e.Pat (Brackets e.WrappedCondVars) : e.Pat^ = : { Success e.Solutions (e.SgNew) (e.ArgNew) , e.SgNew : /* пусто */ + , e.ArgNew : e.ArgNew^ (Brackets e._) + , e.Pat : e.Pat^ (Brackets e._) = ; Success e.Solutions (e.SgNew) (e.ArgNew) + , e.ArgNew : e.ArgNew^ (Brackets e._) + , e.Pat : e.Pat^ (Brackets e._) = ) + (e.ArgNew) (e.Sg ) (/* пусто */) (/* пусто */) e.Begin ((e.Pat) e.Tail) e.Sentences >; @@ -1466,14 +1432,38 @@ DynGenArg { Failure = ((Var 'e')) (/* пусто */) (/* пусто */); }; - (e.Arg) (e.Sg) (e.Sol) (e.Begin) + (e.Arg) (e.Sg) (e.Sol) (e.Begin) /* пусто */ = (e.Arg) (e.Sg) (e.Sol); } +WrappedCondVars { + e.Tail + = ); + + (e.CondVars) (e.Result) + = (e.CondVars); + } + (/* пусто */) + e.Tail + > + : (e.CondVars) + = : e.CondVars^ + = } + e.CondVars + > + : e.CondVars^ + = ; +} + SpecCall-Aux { /* тривиальная сигнатура */ (e.Name) (e.SpecPattern) (e.Body) s.NextNumber e.Signatures (e.OldArg) (e.NewArg) (e.Sg) (e.Solutions) (e.History) + s.NeedRelationCheck , : True = ((e.SpecPattern) (e.Body) s.NextNumber e.Signatures) (CallBrackets (Symbol Name e.Name) e.OldArg) @@ -1482,8 +1472,9 @@ SpecCall-Aux { /* проверяем, известна ли сигнатура */ (e.Name) (e.SpecPattern) (e.Body) s.NextNumber e.Signatures (e.OldArg) (e.NewArg) (e.Sg) (e.Solutions) (e.History) + s.NeedRelationCheck = - : t.State e.Signature + : t._ e.Signature = : { Found e.InstanceName (e.Signatures^) @@ -1496,27 +1487,44 @@ SpecCall-Aux { /* проверяем на зацикливание */ NotFound e.Signatures^ - = ) - e.History - > + = s.NeedRelationCheck + : { + True + = ) + e.History + >; + + False = False; + } : { True e.HistorySignature = : e.GenSignature = : e.ArgVars - = : e.GenSignature^ - = + = + : t._ e.GenSignature^ + = : Clear e.NewSg + = : { - Clear e.NewSg = e.NewSg; - - e.Other = /* пусто */; + /* + Если подстановка e.NewSg является тривиальной, + проверку отношения Хигмана-Крускала + в рекурсивном вызове не выполняем + */ + True = False; + + False = True; } - : e.NewSg + : s.NeedRelationCheck^ + = ) + (/* пусто */) (/* пусто */) e.Body + > + : (e.NewArg^) (e.Sg^) (e.Solutions^) = ) - (e.Solutions) (e.History) + e.Signatures (e.OldArg) (e.NewArg) + (e.Sg) (e.Solutions) (e.History) s.NeedRelationCheck >; False @@ -1567,21 +1575,10 @@ WrapVars { } OrderUniqueVars { - e.Vars - = ; - (e.UniqueVars) (e.ModeIndex) - = (e.UniqueVars (e.ModeIndex)); - } - (/* пусто */) - e.Vars - > - : (e.Vars^) - = e.Vars; + e.Variables = e.Variables; } HasHigmanKruskalRelation {