From 988a8d825f51badff6ee1e1fb82816e8ecf459ae Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:45:49 -0500 Subject: [PATCH 01/27] `TSNode` is no longer defined over `TSLength`, but over `CSize` values instead. --- src/TreeSitter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 2057f68ef..6fc39853b 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -23,7 +23,7 @@ foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime data TSLength = TsLength { bytes :: CSize, chars :: CSize } deriving (Show, Eq) -data TSNode = TsNode { _data :: Ptr (), offset :: TSLength } +data TSNode = TsNode { _data :: Ptr (), offset0 :: CSize, offset1 :: CSize, offset2 :: CSize } deriving (Show, Eq) instance Storable TSNode where From 8550676c42892a4fc9117867fb6033a3f1b5be69 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:49:55 -0500 Subject: [PATCH 02/27] Inline `withNamedChildren` in `toTerm`. --- src/TreeSitter.hs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 6fc39853b..cb39ae834 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -3,7 +3,6 @@ module TreeSitter where import Diff import Range import Parser -import Term import qualified Data.Set as Set import Foreign import Foreign.C @@ -65,13 +64,19 @@ parseTreeSitterFile (Language language constructor) contents = do documentToTerm :: Constructor -> Ptr TSDocument -> Parser documentToTerm constructor document contents = alloca $ \root -> do ts_document_root_node_p document root - snd <$> toTerm root where - toTerm :: Ptr TSNode -> IO (String, Term String Info) - toTerm node = do - name <- ts_node_p_name node document - name <- peekCString name - children <- withNamedChildren node toTerm - return (name, constructor contents (Info (range node) $ Set.singleton name) children) + (_, term) <- toTerm root + return term + where toTerm node = do + name <- ts_node_p_name node document + name <- peekCString name + count <- ts_node_p_named_child_count node + children <- if count == 0 + then return [] + else mapM (alloca . getChild node toTerm) [0..pred count] + return (name, constructor contents (Info (range node) (Set.singleton name)) children) + getChild node transform n out = do + _ <- ts_node_p_named_child node n out + transform out withNamedChildren :: Ptr TSNode -> (Ptr TSNode -> IO (String, a)) -> IO [(String, a)] withNamedChildren node transformNode = do From 5b685f7ce37418351532e26453920b17b038accb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:50:19 -0500 Subject: [PATCH 03/27] Remove `withNamedChildren`. --- src/TreeSitter.hs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index cb39ae834..0de79e01e 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -78,15 +78,5 @@ documentToTerm constructor document contents = alloca $ \root -> do _ <- ts_node_p_named_child node n out transform out -withNamedChildren :: Ptr TSNode -> (Ptr TSNode -> IO (String, a)) -> IO [(String, a)] -withNamedChildren node transformNode = do - count <- ts_node_p_named_child_count node - if count == 0 - then return [] - else mapM (alloca . getChild) [0..pred count] where - getChild n out = do - _ <- ts_node_p_named_child node n out - transformNode out - range :: Ptr TSNode -> Range range node = Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } From f75a0f25f30c27d5af6b152ce707fd54d8d174d9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:50:54 -0500 Subject: [PATCH 04/27] Move `range` into the where clause. --- src/TreeSitter.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 0de79e01e..d5387b8cc 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -77,6 +77,4 @@ documentToTerm constructor document contents = alloca $ \root -> do getChild node transform n out = do _ <- ts_node_p_named_child node n out transform out - -range :: Ptr TSNode -> Range -range node = Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } + range node = Range { start = fromIntegral $! ts_node_p_start_char node, end = fromIntegral $! ts_node_p_end_char node } From a938d072c0ee5a6d8d9a299621445a0f6c953f02 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:52:09 -0500 Subject: [PATCH 05/27] Remove TSLength. --- src/TreeSitter.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index d5387b8cc..b50019387 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -19,9 +19,6 @@ foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_parse" ts_document_parse :: Ptr TSDocument -> IO () foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_free" ts_document_free :: Ptr TSDocument -> IO () -data TSLength = TsLength { bytes :: CSize, chars :: CSize } - deriving (Show, Eq) - data TSNode = TsNode { _data :: Ptr (), offset0 :: CSize, offset1 :: CSize, offset2 :: CSize } deriving (Show, Eq) From 6edd7453e4242b7d87c21bd9970901a48f004088 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:57:15 -0500 Subject: [PATCH 06/27] Attempt to depend on c-storable-deriving again. --- semantic-diff.cabal | 1 + 1 file changed, 1 insertion(+) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index e123f0616..582b56289 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -36,6 +36,7 @@ library , bytestring , blaze-html , tree-sitter-parsers + , c-storable-deriving default-language: Haskell2010 default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable ghc-options: -Wall -fno-warn-name-shadowing From 21ac483558fc5e7106ed42184f7e60d4ff374c2c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 09:58:46 -0500 Subject: [PATCH 07/27] DeriveGeneric. --- semantic-diff.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 582b56289..2addf571b 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -38,7 +38,7 @@ library , tree-sitter-parsers , c-storable-deriving default-language: Haskell2010 - default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable + default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable, DeriveGeneric ghc-options: -Wall -fno-warn-name-shadowing executable semantic-diff-exe From ae92b20a7c9ee1e606174451e3f85d2aa4585659 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:33:36 -0500 Subject: [PATCH 08/27] Derive a Generic instance for `TSNode`. --- src/TreeSitter.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index b50019387..d14fc1c2e 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -7,6 +7,7 @@ import qualified Data.Set as Set import Foreign import Foreign.C import Foreign.C.Types +import qualified GHC.Generics as Generics data TSLanguage = TsLanguage deriving (Show, Eq) foreign import ccall "prototype/doubt-difftool/doubt-difftool-Bridging-Header.h ts_language_c" ts_language_c :: Ptr TSLanguage @@ -20,7 +21,7 @@ foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_free" ts_document_free :: Ptr TSDocument -> IO () data TSNode = TsNode { _data :: Ptr (), offset0 :: CSize, offset1 :: CSize, offset2 :: CSize } - deriving (Show, Eq) + deriving (Show, Eq, Generics.Generic) instance Storable TSNode where alignment _ = 32 From 44ba628c7122143fb4185b7f8980065b3b8e9d32 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:33:52 -0500 Subject: [PATCH 09/27] Add a default CStorable instance for TSNode. --- src/TreeSitter.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index d14fc1c2e..fe51c338f 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -7,6 +7,7 @@ import qualified Data.Set as Set import Foreign import Foreign.C import Foreign.C.Types +import Foreign.CStorable import qualified GHC.Generics as Generics data TSLanguage = TsLanguage deriving (Show, Eq) @@ -23,6 +24,7 @@ foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime data TSNode = TsNode { _data :: Ptr (), offset0 :: CSize, offset1 :: CSize, offset2 :: CSize } deriving (Show, Eq, Generics.Generic) +instance CStorable TSNode instance Storable TSNode where alignment _ = 32 sizeOf _ = 32 From 038d0b6ff68562a90a421bfc9a40d82bd5ae7f2b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:34:08 -0500 Subject: [PATCH 10/27] Implement the Storable instance for TSNode in terms of its CStorable instance. --- src/TreeSitter.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index fe51c338f..58db07763 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -26,10 +26,10 @@ data TSNode = TsNode { _data :: Ptr (), offset0 :: CSize, offset1 :: CSize, offs instance CStorable TSNode instance Storable TSNode where - alignment _ = 32 - sizeOf _ = 32 - peek _ = error "Haskell code should never read TSNode values directly." - poke _ _ = error "Haskell code should never write TSNode values directly." + alignment = cAlignment + sizeOf = cSizeOf + peek = cPeek + poke = cPoke foreign import ccall "app/bridge.h ts_document_root_node_p" ts_document_root_node_p :: Ptr TSDocument -> Ptr TSNode -> IO () foreign import ccall "app/bridge.h ts_node_p_name" ts_node_p_name :: Ptr TSNode -> Ptr TSDocument -> IO CString From a32de112183dc6e3c87730c8915ea9e9760b7cb9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:34:40 -0500 Subject: [PATCH 11/27] Spacing. --- src/TreeSitter.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 58db07763..6ba223724 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -54,7 +54,7 @@ parseTreeSitterFile :: Language -> Parser parseTreeSitterFile (Language language constructor) contents = do document <- ts_document_make ts_document_set_language document language - withCString contents (\source -> do + withCString contents (\ source -> do ts_document_set_input_string document source ts_document_parse document term <- documentToTerm constructor document contents @@ -62,7 +62,7 @@ parseTreeSitterFile (Language language constructor) contents = do return term) documentToTerm :: Constructor -> Ptr TSDocument -> Parser -documentToTerm constructor document contents = alloca $ \root -> do +documentToTerm constructor document contents = alloca $ \ root -> do ts_document_root_node_p document root (_, term) <- toTerm root return term From 308e5616935079a15f7206311e42e4a7825d8217 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:43:41 -0500 Subject: [PATCH 12/27] Use `take` to specify a half-open interval. --- src/TreeSitter.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 6ba223724..45b837a90 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -70,9 +70,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do name <- ts_node_p_name node document name <- peekCString name count <- ts_node_p_named_child_count node - children <- if count == 0 - then return [] - else mapM (alloca . getChild node toTerm) [0..pred count] + children <- mapM (alloca . getChild node toTerm) $ take (fromIntegral count) [0..] return (name, constructor contents (Info (range node) (Set.singleton name)) children) getChild node transform n out = do _ <- ts_node_p_named_child node n out From 76e1f042c8ca5ed60251fd81dc31074cf7ab57a9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 10:47:15 -0500 Subject: [PATCH 13/27] `getChild` calls `toTerm` directly. --- src/TreeSitter.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 45b837a90..71a96d9da 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -70,9 +70,9 @@ documentToTerm constructor document contents = alloca $ \ root -> do name <- ts_node_p_name node document name <- peekCString name count <- ts_node_p_named_child_count node - children <- mapM (alloca . getChild node toTerm) $ take (fromIntegral count) [0..] + children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] return (name, constructor contents (Info (range node) (Set.singleton name)) children) - getChild node transform n out = do + getChild node n out = do _ <- ts_node_p_named_child node n out - transform out + toTerm out range node = Range { start = fromIntegral $! ts_node_p_start_char node, end = fromIntegral $! ts_node_p_end_char node } From aca7b55784485a269731cddfa6b49c98289eea92 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:37:42 -0500 Subject: [PATCH 14/27] Capture the range in a temporary. --- src/TreeSitter.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 71a96d9da..113d6ece6 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -71,7 +71,8 @@ documentToTerm constructor document contents = alloca $ \ root -> do name <- peekCString name count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] - return (name, constructor contents (Info (range node) (Set.singleton name)) children) + range <- return $ range node + return (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out From 08c2d72803007330d416ec6291c5d411ddc488b0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:38:09 -0500 Subject: [PATCH 15/27] Force the evaluation of the range. --- src/TreeSitter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 113d6ece6..7197a2f57 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -72,7 +72,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] range <- return $ range node - return (name, constructor contents (Info range (Set.singleton name)) children) + return $! range `seq` (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out From eb908e4fa2908ecc0f8254a7a6a622d6d7c33e11 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:39:13 -0500 Subject: [PATCH 16/27] Compute the range in-place. --- src/TreeSitter.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 7197a2f57..6ff15d76e 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -71,9 +71,8 @@ documentToTerm constructor document contents = alloca $ \ root -> do name <- peekCString name count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] - range <- return $ range node + range <- return $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } return $! range `seq` (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out - range node = Range { start = fromIntegral $! ts_node_p_start_char node, end = fromIntegral $! ts_node_p_end_char node } From a8578ccbf809f78d5e06854fbe1e911a748e9d2f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:39:40 -0500 Subject: [PATCH 17/27] Force the evaluation of the start & end of the range. --- src/TreeSitter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 6ff15d76e..d3a61d49d 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -72,7 +72,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] range <- return $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } - return $! range `seq` (name, constructor contents (Info range (Set.singleton name)) children) + return $! start range `seq` end range `seq` (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out From 24998db34eadc9c80c16c05ed48203f3f63cb920 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:41:35 -0500 Subject: [PATCH 18/27] =?UTF-8?q?Range=E2=80=99s=20fields=20are=20strict.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Range.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Range.hs b/src/Range.hs index e02451b34..fc1512740 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -3,7 +3,7 @@ module Range where import Control.Applicative ((<|>)) import qualified Data.Char as Char -data Range = Range { start :: Int, end :: Int } +data Range = Range { start :: !Int, end :: !Int } deriving (Eq, Show) substring :: Range -> String -> String From fe347b3f074cc1abb7c1a27e48ff60ce630db28a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:41:55 -0500 Subject: [PATCH 19/27] =?UTF-8?q?Just=20force=20the=20evaluation=20of=20`r?= =?UTF-8?q?ange`=20now=20that=20it=E2=80=99s=20strict.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TreeSitter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index d3a61d49d..6ff15d76e 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -72,7 +72,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] range <- return $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } - return $! start range `seq` end range `seq` (name, constructor contents (Info range (Set.singleton name)) children) + return $! range `seq` (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out From ab7f74866313c8a35a2bca1ccbe10f134440aea0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:48:43 -0500 Subject: [PATCH 20/27] Use fromMaybe to expand the alternatives. --- src/Range.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Range.hs b/src/Range.hs index fc1512740..46450135a 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -2,6 +2,7 @@ module Range where import Control.Applicative ((<|>)) import qualified Data.Char as Char +import Data.Maybe (fromMaybe) data Range = Range { start :: !Int, end :: !Int } deriving (Eq, Show) @@ -17,7 +18,7 @@ offsetRange i (Range start end) = Range (i + start) (i + end) rangesAndWordsFrom :: Int -> String -> [(Range, String)] rangesAndWordsFrom _ "" = [] -rangesAndWordsFrom startIndex string = maybe [] id $ takeAndContinue <$> (word <|> punctuation) <|> skipAndContinue <$> space +rangesAndWordsFrom startIndex string = fromMaybe [] $ takeAndContinue <$> (word <|> punctuation) <|> skipAndContinue <$> space where word = parse isWord string punctuation = parse (not . isWordOrSpace) string From 077c8194b2cf2e9b246d9d126f4392d49f79bea6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:49:59 -0500 Subject: [PATCH 21/27] Spacing. --- src/Diff.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Diff.hs b/src/Diff.hs index 624c95f66..85b311c81 100644 --- a/src/Diff.hs +++ b/src/Diff.hs @@ -11,7 +11,6 @@ import Categorizable data Annotated a annotation f = Annotated annotation (Syntax a f) deriving (Functor, Eq, Show, Foldable) - type Category = String data Info = Info { characterRange :: Range, categories :: (Set Category) } deriving (Eq, Show) From d30bc17c16863d5f33f75ba19955a38feee3ea21 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:50:26 -0500 Subject: [PATCH 22/27] Remove redundant parentheses. --- src/Diff.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Diff.hs b/src/Diff.hs index 85b311c81..5b1bcd725 100644 --- a/src/Diff.hs +++ b/src/Diff.hs @@ -12,7 +12,7 @@ data Annotated a annotation f = Annotated annotation (Syntax a f) deriving (Functor, Eq, Show, Foldable) type Category = String -data Info = Info { characterRange :: Range, categories :: (Set Category) } +data Info = Info { characterRange :: Range, categories :: Set Category } deriving (Eq, Show) instance Categorizable Info where From 98bde6b555dddeae6aa2680e28c90fb42c33cd44 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:50:29 -0500 Subject: [PATCH 23/27] Eta reduction. --- src/Diff.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Diff.hs b/src/Diff.hs index 5b1bcd725..1da0c6edf 100644 --- a/src/Diff.hs +++ b/src/Diff.hs @@ -16,7 +16,7 @@ data Info = Info { characterRange :: Range, categories :: Set Category } deriving (Eq, Show) instance Categorizable Info where - categories info = Diff.categories info + categories = Diff.categories type Diff a annotation = Free (Annotated a (annotation, annotation)) (Patch (Term a annotation)) From 094fd90f911c1b28d7b7e4f0935c4c76733d6d39 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:51:52 -0500 Subject: [PATCH 24/27] Info is now strict. --- src/Diff.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Diff.hs b/src/Diff.hs index 1da0c6edf..2bd52b655 100644 --- a/src/Diff.hs +++ b/src/Diff.hs @@ -12,7 +12,7 @@ data Annotated a annotation f = Annotated annotation (Syntax a f) deriving (Functor, Eq, Show, Foldable) type Category = String -data Info = Info { characterRange :: Range, categories :: Set Category } +data Info = Info { characterRange :: !Range, categories :: !(Set Category) } deriving (Eq, Show) instance Categorizable Info where From 319bbecfdb58fd2150ad28c8f18860e8e83f23f2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:52:04 -0500 Subject: [PATCH 25/27] We no longer need to force the evaluation of `range`. --- src/TreeSitter.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 6ff15d76e..b0740b2e3 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -72,7 +72,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] range <- return $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } - return $! range `seq` (name, constructor contents (Info range (Set.singleton name)) children) + return (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do _ <- ts_node_p_named_child node n out toTerm out From 92cbad56fe86e771a7ae27d382b72bcf7578c225 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:54:28 -0500 Subject: [PATCH 26/27] Document why strict application. --- src/TreeSitter.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index b0740b2e3..a0b0e167a 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -71,6 +71,7 @@ documentToTerm constructor document contents = alloca $ \ root -> do name <- peekCString name count <- ts_node_p_named_child_count node children <- mapM (alloca . getChild node) $ take (fromIntegral count) [0..] + -- Note: The strict application here is semantically important. Without it, we may not evaluate the range until after we’ve exited the scope that `node` was allocated within, meaning `alloca` will free it & other stack data may overwrite it. range <- return $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node } return (name, constructor contents (Info range (Set.singleton name)) children) getChild node n out = do From 745ee358166e3c2ce8509a83319bc11ffbad8ebb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Dec 2015 17:55:19 -0500 Subject: [PATCH 27/27] Annotated is strict in its annotation and syntax.. --- src/Diff.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Diff.hs b/src/Diff.hs index 2bd52b655..7a5d9d317 100644 --- a/src/Diff.hs +++ b/src/Diff.hs @@ -8,7 +8,7 @@ import Term import Range import Categorizable -data Annotated a annotation f = Annotated annotation (Syntax a f) +data Annotated a annotation f = Annotated !annotation !(Syntax a f) deriving (Functor, Eq, Show, Foldable) type Category = String