Skip to content
This repository has been archived by the owner on Jan 2, 2021. It is now read-only.

Extend position mapping with fuzzy ranges #785

Merged
merged 4 commits into from
Sep 13, 2020
Merged

Conversation

wz1000
Copy link
Collaborator

@wz1000 wz1000 commented Sep 12, 2020

We sometimes need to know the original range that a position mapped to, when a simple failure is not helpful.
For example, when the user is typing inside a do block, we would like to use position mapping to tell us that the current cursor position is within the span of the do block, where the span is known from the old version of the file for which we have compiler artifacts. This can be helpful for things like generating completions based on local variables.

Copy link
Collaborator

@pepeiborra pepeiborra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, just add the missing bangs and good to merge

src/Development/IDE/Core/PositionMapping.hs Outdated Show resolved Hide resolved
@wz1000
Copy link
Collaborator Author

wz1000 commented Sep 13, 2020

I'm a bit concerned about adding bangs to the datatype definition, I must admit. I think it changes the asymptotics of 'n' binds in sequence from linear to exponential. Let me confirm by writing a synthetic benchmark.

@wz1000
Copy link
Collaborator Author

wz1000 commented Sep 13, 2020

Yes, its as I suspected.

Here is the benchmark I'm using

f :: Int -> PositionResult Int
f i = PositionRange (i-1) (i+1)

g :: Int -> Int -> PositionResult Int
g 0 x = pure x
g i x = f x >>= g (i-1)

main :: IO ()
main = do
  print $ g 100 0

with

data PositionResult a = PositionRange { unsafeLowerRange :: !a, unsafeUpperRange :: !a } | PositionExact !a

This doesn't terminate any time soon.

It terminates pretty much instantly with the following:

data PositionResult a = PositionRange { unsafeLowerRange :: a, unsafeUpperRange :: a } | PositionExact !a

It also terminates if we add bangs to the Monad instance:

instance Monad PositionResult where
  (PositionExact a) >>= f = f a
  (PositionRange !lower !upper) >>= f = PositionRange lower' upper'
    where
      lower' = lowerRange $ f lower
      upper' = upperRange $ f upper

However, adding bangs to lower' and upper' makes it diverge again

@pepeiborra
Copy link
Collaborator

Wow, good catch!

@pepeiborra pepeiborra merged commit b980c33 into haskell:master Sep 13, 2020
pepeiborra pushed a commit to pepeiborra/ide that referenced this pull request Dec 29, 2020
* Extend position mapping with fuzzy ranges

* fix tests

* add bangs

* make fields lazy again
pepeiborra pushed a commit to pepeiborra/ide that referenced this pull request Dec 29, 2020
* Extend position mapping with fuzzy ranges

* fix tests

* add bangs

* make fields lazy again
pepeiborra pushed a commit to pepeiborra/ide that referenced this pull request Dec 29, 2020
* Extend position mapping with fuzzy ranges

* fix tests

* add bangs

* make fields lazy again
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants