Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/Elm/Parser/Expression.elm
Original file line number Diff line number Diff line change
Expand Up @@ -1515,7 +1515,10 @@ infixNonAssociative leftPrecedence symbol =
temporaryErrPrecedenceTooHigh
)
(\info ->
if info.leftPrecedence == leftPrecedence then
-- `(a - b) == 0` compiles to `=== 0` (literal-Int path);
-- `a == b` between two non-literal Ints compiles to
-- `_Utils_eq(a, b)` which allocates a stack array per call.
if info.leftPrecedence - leftPrecedence == 0 then
problemCannotMixNonAssociativeInfixOperators

else
Expand Down
26 changes: 19 additions & 7 deletions src/Elm/Parser/Layout.elm
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,28 @@ whitespaceAndCommentsOrEmpty =
-- whitespace can't be followed by more whitespace
--
-- since comments are comparatively rare
-- but expensive to check for, we allow shortcutting
-- but expensive to check for, we allow shortcutting.
--
-- Check the first char alone (1-char slice) before paying for a 2-char
-- slice + multi-string compare. Almost every call lands in the `_`
-- branch and that path allocates one less substring.
(ParserFast.offsetSourceAndThenOrSucceed
(\offset source ->
case source |> String.slice offset (offset + 2) of
"--" ->
-- this will always succeed from here, so no need to fall back to Rope.empty
Just fromSingleLineCommentNode
case String.slice offset (offset + 1) source of
"-" ->
if String.slice (offset + 1) (offset + 2) source == "-" then
-- this will always succeed from here, so no need to fall back to Rope.empty
Just fromSingleLineCommentNode

else
Nothing

"{" ->
if String.slice (offset + 1) (offset + 2) source == "-" then
Just fromMultilineCommentNodeOrEmptyOnProblem

"{-" ->
Just fromMultilineCommentNodeOrEmptyOnProblem
else
Nothing

Comment thread
Arkham marked this conversation as resolved.
_ ->
Nothing
Expand Down
37 changes: 31 additions & 6 deletions src/ParserFast.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2494,12 +2494,16 @@ anyChar =
newOffset =
charOrEnd s.offset s.src
in
if newOffset == -1 then
-- `newOffset + 1 == 0` iff `newOffset == -1`. We add then compare to
-- the literal 0 so the Elm compiler emits `=== 0` instead of
-- `_Utils_eq(newOffset, -1)` (which allocates a stack array).
-- See the `isSubCharWithoutLinebreak` docstring below.
if newOffset + 1 == 0 then
-- end of source
Bad False (ExpectingAnyChar s.row s.col)

else if newOffset == -2 then
Comment thread
Arkham marked this conversation as resolved.
-- newline
else if newOffset < 0 then
-- newline (-2; we already filtered -1 above)
Good '\n'
{ src = s.src
, offset = s.offset + 1
Expand Down Expand Up @@ -2810,7 +2814,18 @@ whileWithoutLinebreakAnd2PartUtf16ToResultAndThen whileCharIsOkay consumedString
whileCharIsOkay
s0.offset
s0.src
in
-- Short-circuit when no chars were consumed: fires after every
-- expression not followed by an infix operator (very common).
-- Skips the empty-string slice + callback dispatch that would
-- otherwise allocate a Bad+ExpectingCustom record.
-- `(a - b) == 0` compiles to `=== 0`; plain `a == b` on Ints
-- compiles to `_Utils_eq` which allocates.
if s1Offset - s0.offset == 0 then
Bad False (ExpectingCharSatisfyingPredicate s0.row s0.col)

else
let
whileContent : String
whileContent =
String.slice s0.offset s1Offset s0.src
Expand Down Expand Up @@ -3039,7 +3054,14 @@ nestableMultiCommentMapWithRange rangeContentToRes ( openChar, openTail ) ( clos
charCode =
Char.toCode char
in
charCode /= openCharCode && charCode /= closeCharCode && not (Char.Extra.isUtf16Surrogate char)
-- Subtract-and-compare-to-literal-0 forces the Elm compiler to
-- emit `!== 0` instead of `_Utils_eq(int, int)` (the latter
-- allocates a stack array per call). This predicate runs once per
-- char inside multi-line comment bodies — very hot in elm-package
-- corpora which have many doc comments.
(charCode - openCharCode /= 0)
&& (charCode - closeCharCode /= 0)
&& not (Char.Extra.isUtf16Surrogate char)
in
map2WithRange
(\range afterOpen contentAfterAfterOpen ->
Expand Down Expand Up @@ -3142,15 +3164,18 @@ anyCharFollowedByWhileMap consumedStringToRes afterFirstIsOkay =
firstOffset =
charOrEnd s.offset s.src
in
if firstOffset == -1 then
-- `firstOffset + 1 == 0` iff `firstOffset == -1`. See `isSubCharWithoutLinebreak`
-- docstring below for why this (vs `== -1`) matters.
if firstOffset + 1 == 0 then
-- end of source
Bad False (ExpectingAnyChar s.row s.col)

else
let
s1 : State
s1 =
if firstOffset == -2 then
if firstOffset < 0 then
-- newline (-2; we already filtered -1 above)
skipWhileHelp afterFirstIsOkay (s.offset + 1) (s.row + 1) 1 s.src s.indent

else
Expand Down