Mise à jour terminée. Pour connaître les apports de la version 13.8.4 par rapport à notre ancienne version vous pouvez lire les "Release Notes" suivantes :
https://about.gitlab.com/releases/2021/02/11/security-release-gitlab-13-8-4-released/
https://about.gitlab.com/releases/2021/02/05/gitlab-13-8-3-released/

Commit 5af20d78 authored by POTTIER Francois's avatar POTTIER Francois

Improved [KeywordExpansion] by also optimizing symbols that generate a subset of {epsilon}.

parent 9eddb2e6
...@@ -19,11 +19,12 @@ let posvar_ = function ...@@ -19,11 +19,12 @@ let posvar_ = function
[Parsing.symbol_start_pos] in OCaml's standard library. *) [Parsing.symbol_start_pos] in OCaml's standard library. *)
(* This cascade of [if] constructs could be quite big, and this could be a (* This cascade of [if] constructs could be quite big, and this could be a
problem in terms of code size. Fortunately, because we know which symbols are problem in terms of code size. Fortunately, we can optimize this code by
nullable, we can optimize this code by computing, ahead of time, the outcome computing, ahead of time, the outcome of certain comparisons. We assume that
of certain comparisons. This assumes that the lexer never produces a token the lexer never produces a token whose start and end positions are the same.
whose start and end positions are the same. There follows that a non-nullable There follows that a non-nullable symbol cannot have the same start and end
symbol cannot have the same start and end positions. *) positions. Conversely, a symbol that generates (a subset of) the language
{epsilon} must have the same start and end positions. *)
(* Although this code is modeled after [Parsing.symbol_start_pos], we compare (* Although this code is modeled after [Parsing.symbol_start_pos], we compare
positions using physical equality, whereas they use structural equality. If positions using physical equality, whereas they use structural equality. If
...@@ -40,7 +41,8 @@ let posvar_ = function ...@@ -40,7 +41,8 @@ let posvar_ = function
symbol, once inlined, can be seen to be a sequence of empty and nonempty symbol, once inlined, can be seen to be a sequence of empty and nonempty
symbols. *) symbols. *)
let rec symbolstartpos nullable producers i n : IL.expr * KeywordSet.t = let rec symbolstartpos ((nullable, epsilon) as analysis) producers i n
: IL.expr * KeywordSet.t =
if i = n then if i = n then
(* Return [$endpos]. *) (* Return [$endpos]. *)
let keyword = Position (Left, WhereEnd, FlavorPosition) in let keyword = Position (Left, WhereEnd, FlavorPosition) in
...@@ -56,16 +58,23 @@ let rec symbolstartpos nullable producers i n : IL.expr * KeywordSet.t = ...@@ -56,16 +58,23 @@ let rec symbolstartpos nullable producers i n : IL.expr * KeywordSet.t =
let startp = Position (RightNamed x, WhereStart, FlavorPosition) let startp = Position (RightNamed x, WhereStart, FlavorPosition)
and endp = Position (RightNamed x, WhereEnd, FlavorPosition) in and endp = Position (RightNamed x, WhereEnd, FlavorPosition) in
if not (nullable symbol) then if not (nullable symbol) then
(* The start and end positions must differ. *)
EVar (posvar_ startp), EVar (posvar_ startp),
KeywordSet.singleton startp KeywordSet.singleton startp
else else
let continue, keywords = symbolstartpos nullable producers (i + 1) n in let continue, keywords = symbolstartpos analysis producers (i + 1) n in
EIfThenElse ( if epsilon symbol then
EApp (EVar "Pervasives.(!=)", [ EVar (posvar_ startp); EVar (posvar_ endp) ]), (* The start and end positions must be the same. *)
EVar (posvar_ startp), continue,
continue keywords
), else
KeywordSet.add startp (KeywordSet.add endp keywords) (* In the general case, a runtime test is required. *)
EIfThenElse (
EApp (EVar "Pervasives.(!=)", [ EVar (posvar_ startp); EVar (posvar_ endp) ]),
EVar (posvar_ startp),
continue
),
KeywordSet.add startp (KeywordSet.add endp keywords)
(* [define keyword1 f keyword2] macro-expands [keyword1] as [f(keyword2)], (* [define keyword1 f keyword2] macro-expands [keyword1] as [f(keyword2)],
where [f] is a function of expressions to expressions. *) where [f] is a function of expressions to expressions. *)
...@@ -94,10 +103,10 @@ let expand_ofs keyword action = ...@@ -94,10 +103,10 @@ let expand_ofs keyword action =
(* [$symbolstartpos] is expanded into a cascade of [if] constructs, modeled (* [$symbolstartpos] is expanded into a cascade of [if] constructs, modeled
after [Parsing.symbol_start_pos]. *) after [Parsing.symbol_start_pos]. *)
let expand_symbolstartpos nullable producers n keyword action = let expand_symbolstartpos analysis producers n keyword action =
match keyword with match keyword with
| Position (Left, WhereSymbolStart, FlavorPosition) -> | Position (Left, WhereSymbolStart, FlavorPosition) ->
let expansion, keywords = symbolstartpos nullable producers 0 n in let expansion, keywords = symbolstartpos analysis producers 0 n in
Action.define keyword keywords Action.define keyword keywords
(mlet [ PVar (posvar_ keyword) ] [ expansion ]) (mlet [ PVar (posvar_ keyword) ] [ expansion ])
action action
...@@ -150,7 +159,7 @@ let expand_round f action = ...@@ -150,7 +159,7 @@ let expand_round f action =
can cause new keywords to appear, which must eliminated by the following can cause new keywords to appear, which must eliminated by the following
rounds. *) rounds. *)
let expand_action nullable producers action = let expand_action analysis producers action =
let n = List.length producers in let n = List.length producers in
(* The [ofs] keyword family is defined in terms of the [pos] family by (* The [ofs] keyword family is defined in terms of the [pos] family by
...@@ -160,7 +169,7 @@ let expand_action nullable producers action = ...@@ -160,7 +169,7 @@ let expand_action nullable producers action =
(* Expand [$symbolstartpos] away. *) (* Expand [$symbolstartpos] away. *)
let action = expand_round (expand_symbolstartpos nullable producers n) action in let action = expand_round (expand_symbolstartpos analysis producers n) action in
(* Then, expand away the non-[ofs] keywords. *) (* Then, expand away the non-[ofs] keywords. *)
...@@ -168,26 +177,34 @@ let expand_action nullable producers action = ...@@ -168,26 +177,34 @@ let expand_action nullable producers action =
action action
let expand_branch nullable branch = (* Silently analyze the grammar so as to find out which symbols are
{ branch with action = expand_action nullable branch.producers branch.action } nullable and which symbols generate a subset of {epsilon}. This
is used to optimize the expansion of $symbolstartpos. *)
let expand_rule nullable rule = let analysis grammar =
{ rule with branches = List.map (expand_branch nullable) rule.branches }
let expand_grammar grammar =
(* Silently analyze the grammar so as to find out which symbols are
nullable. This is used to optimize the expansion of the keyword
$symbolstartpos. *)
let module G = GrammarFunctor.Make(struct let module G = GrammarFunctor.Make(struct
let grammar = grammar let grammar = grammar
let verbose = false let verbose = false
end) in end) in
let nullable (nt : Syntax.symbol) : bool = let lookup (nt : Syntax.symbol) : G.Symbol.t =
G.Analysis.nullable_symbol (try try G.Symbol.lookup nt with Not_found -> assert false
G.Symbol.lookup nt
with Not_found ->
assert false
)
in in
{ grammar with rules = StringMap.map (expand_rule nullable) grammar.rules } let nullable nt : bool =
G.Analysis.nullable_symbol (lookup nt)
and epsilon nt : bool =
G.TerminalSet.is_empty (G.Analysis.first_symbol (lookup nt))
in
nullable, epsilon
(* Put everything together. *)
let expand_branch analysis branch =
{ branch with action = expand_action analysis branch.producers branch.action }
let expand_rule analysis rule =
{ rule with branches = List.map (expand_branch analysis) rule.branches }
let expand_grammar grammar =
let analysis = analysis grammar in
{ grammar with rules = StringMap.map (expand_rule analysis) grammar.rules }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment