2015-11-18 01:44:16 +03:00
|
|
|
module Main where
|
|
|
|
|
2015-11-27 20:22:05 +03:00
|
|
|
import Categorizable
|
2015-11-18 22:45:23 +03:00
|
|
|
import Diff
|
2015-11-27 20:22:05 +03:00
|
|
|
import Interpreter
|
2015-11-18 22:45:23 +03:00
|
|
|
import Patch
|
|
|
|
import Syntax
|
2015-11-27 20:41:38 +03:00
|
|
|
import Term
|
2015-11-27 20:42:00 +03:00
|
|
|
import Unified
|
2015-11-18 22:45:23 +03:00
|
|
|
import Control.Comonad.Cofree
|
2015-11-27 20:42:00 +03:00
|
|
|
import Control.Monad
|
2015-11-25 17:56:14 +03:00
|
|
|
import Control.Monad.Free hiding (unfoldM)
|
2015-11-27 17:19:09 +03:00
|
|
|
import qualified Data.Map as Map
|
2015-11-27 20:42:00 +03:00
|
|
|
import qualified Data.ByteString.Char8 as ByteString
|
2015-11-21 00:21:09 +03:00
|
|
|
import Data.Maybe
|
2015-11-20 19:50:11 +03:00
|
|
|
import Data.Set
|
2015-11-20 19:36:54 +03:00
|
|
|
import System.Environment
|
2015-11-18 22:45:23 +03:00
|
|
|
|
2015-11-24 21:15:45 +03:00
|
|
|
import Foreign
|
2015-11-25 00:40:47 +03:00
|
|
|
import Foreign.C
|
2015-11-24 21:15:45 +03:00
|
|
|
import Foreign.C.Types
|
2015-11-24 21:50:10 +03:00
|
|
|
import Foreign.C.String
|
2015-11-25 00:40:47 +03:00
|
|
|
import Foreign.ForeignPtr.Unsafe
|
2015-11-24 21:15:45 +03:00
|
|
|
|
2015-11-26 22:03:53 +03:00
|
|
|
data TSLanguage = TsLanguage deriving (Show, Eq)
|
2015-11-25 18:06:14 +03:00
|
|
|
foreign import ccall "prototype/doubt-difftool/doubt-difftool-Bridging-Header.h ts_language_c" ts_language_c :: IO (Ptr TSLanguage)
|
2015-11-18 22:45:23 +03:00
|
|
|
|
2015-11-26 22:03:53 +03:00
|
|
|
data TSDocument = TsDocument deriving (Show, Eq)
|
2015-11-25 18:06:14 +03:00
|
|
|
foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_make" ts_document_make :: IO (Ptr TSDocument)
|
|
|
|
foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_set_language" ts_document_set_language :: Ptr TSDocument -> Ptr TSLanguage -> IO ()
|
|
|
|
foreign import ccall "prototype/External/tree-sitter/include/tree_sitter/runtime.h ts_document_set_input_string" ts_document_set_input_string :: Ptr TSDocument -> CString -> IO ()
|
|
|
|
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 ()
|
2015-11-24 21:23:29 +03:00
|
|
|
|
2015-11-26 02:32:05 +03:00
|
|
|
data TSLength = TsLength { bytes :: CSize, chars :: CSize }
|
2015-11-26 22:03:53 +03:00
|
|
|
deriving (Show, Eq)
|
2015-11-25 00:39:31 +03:00
|
|
|
|
2015-11-26 02:32:05 +03:00
|
|
|
data TSNode = TsNode { _data :: Ptr (), offset :: TSLength }
|
2015-11-26 22:03:53 +03:00
|
|
|
deriving (Show, Eq)
|
2015-11-25 00:39:42 +03:00
|
|
|
|
|
|
|
instance Storable TSNode where
|
2015-11-26 02:32:17 +03:00
|
|
|
alignment n = 24
|
|
|
|
sizeOf n = 24
|
2015-11-27 00:21:54 +03:00
|
|
|
peek p = error "Haskell code should never read TSNode values directly."
|
|
|
|
poke p n = error "Haskell code should never write TSNode values directly."
|
2015-11-25 00:39:42 +03:00
|
|
|
|
|
|
|
foreign import ccall "app/bridge.h ts_document_root_node_p" ts_document_root_node_p :: Ptr TSDocument -> Ptr TSNode -> IO ()
|
2015-11-25 20:24:07 +03:00
|
|
|
foreign import ccall "app/bridge.h ts_node_p_name" ts_node_p_name :: Ptr TSNode -> Ptr TSDocument -> IO CString
|
|
|
|
foreign import ccall "app/bridge.h ts_node_p_named_child_count" ts_node_p_named_child_count :: Ptr TSNode -> IO CSize
|
|
|
|
foreign import ccall "app/bridge.h ts_node_p_named_child" ts_node_p_named_child :: Ptr TSNode -> CSize -> Ptr TSNode -> IO CSize
|
2015-11-25 20:50:22 +03:00
|
|
|
foreign import ccall "app/bridge.h ts_node_p_pos_chars" ts_node_p_pos_chars :: Ptr TSNode -> IO CSize
|
|
|
|
foreign import ccall "app/bridge.h ts_node_p_size_chars" ts_node_p_size_chars :: Ptr TSNode -> IO CSize
|
2015-11-24 22:08:08 +03:00
|
|
|
|
2015-11-18 01:44:16 +03:00
|
|
|
main :: IO ()
|
2015-11-20 19:36:54 +03:00
|
|
|
main = do
|
2015-11-25 00:51:53 +03:00
|
|
|
args <- getArgs
|
2015-11-27 20:42:00 +03:00
|
|
|
output <- let (a, b) = files args in do
|
|
|
|
aContents <- readFile a
|
|
|
|
bContents <- readFile b
|
|
|
|
aTerm <- parseTreeSitterFile aContents
|
|
|
|
bTerm <- parseTreeSitterFile bContents
|
|
|
|
unified (interpret comparable aTerm bTerm) aContents bContents
|
|
|
|
ByteString.putStr output
|
2015-11-25 00:51:53 +03:00
|
|
|
|
2015-11-27 20:42:00 +03:00
|
|
|
parseTreeSitterFile :: String -> IO (Term String Info)
|
|
|
|
parseTreeSitterFile contents = do
|
2015-11-24 21:41:30 +03:00
|
|
|
document <- ts_document_make
|
2015-11-24 21:45:54 +03:00
|
|
|
language <- ts_language_c
|
2015-11-24 21:46:00 +03:00
|
|
|
ts_document_set_language document language
|
2015-11-27 00:24:57 +03:00
|
|
|
withCString contents (\source -> do
|
|
|
|
ts_document_set_input_string document source
|
|
|
|
ts_document_parse document
|
|
|
|
term <- documentToTerm document contents
|
2015-11-27 00:25:55 +03:00
|
|
|
ts_document_free document
|
|
|
|
return term)
|
2015-11-25 18:41:37 +03:00
|
|
|
|
2015-11-27 00:22:27 +03:00
|
|
|
documentToTerm :: Ptr TSDocument -> String -> IO (Term String Info)
|
|
|
|
documentToTerm document contents = alloca $ \root -> do
|
2015-11-27 00:09:16 +03:00
|
|
|
ts_document_root_node_p document root
|
2015-11-27 17:19:02 +03:00
|
|
|
snd <$> toTerm root where
|
|
|
|
toTerm :: Ptr TSNode -> IO (String, Term String Info)
|
2015-11-27 00:07:04 +03:00
|
|
|
toTerm node = do
|
|
|
|
name <- ts_node_p_name node document
|
|
|
|
name <- peekCString name
|
|
|
|
children <- withNamedChildren node toTerm
|
|
|
|
range <- range node
|
2015-11-27 00:15:56 +03:00
|
|
|
annotation <- return . Info range $ singleton name
|
2015-11-27 17:19:02 +03:00
|
|
|
return (name, annotation :< case children of
|
2015-11-27 00:07:04 +03:00
|
|
|
[] -> Leaf $ substring range contents
|
2015-11-27 17:19:40 +03:00
|
|
|
_ | member name keyedProductions -> Keyed $ Map.fromList children
|
2015-11-27 17:19:02 +03:00
|
|
|
_ | member name fixedProductions -> Fixed $ fmap snd children
|
|
|
|
_ | otherwise -> Indexed $ fmap snd children)
|
2015-11-27 00:07:04 +03:00
|
|
|
|
2015-11-27 00:15:39 +03:00
|
|
|
keyedProductions = fromList [ "object" ]
|
|
|
|
fixedProductions = fromList [ "pair", "rel_op", "math_op", "bool_op", "bitwise_op", "type_op", "math_assignment", "assignment", "subscript_access", "member_access", "new_expression", "function_call", "function", "ternary" ]
|
2015-11-20 19:36:54 +03:00
|
|
|
|
2015-11-27 17:19:02 +03:00
|
|
|
withNamedChildren :: Ptr TSNode -> (Ptr TSNode -> IO (String, a)) -> IO [(String, a)]
|
2015-11-27 00:28:17 +03:00
|
|
|
withNamedChildren node transformNode = do
|
2015-11-25 20:05:25 +03:00
|
|
|
count <- ts_node_p_named_child_count node
|
2015-11-26 01:09:42 +03:00
|
|
|
if count == 0
|
|
|
|
then return []
|
2015-11-27 00:27:57 +03:00
|
|
|
else mapM (alloca . getChild) [0..pred count] where
|
|
|
|
getChild n out = do
|
2015-11-26 01:09:42 +03:00
|
|
|
ts_node_p_named_child node n out
|
2015-11-27 00:28:17 +03:00
|
|
|
transformNode out
|
2015-11-25 20:05:25 +03:00
|
|
|
|
2015-11-25 20:51:11 +03:00
|
|
|
range :: Ptr TSNode -> IO Range
|
|
|
|
range node = do
|
|
|
|
pos <- ts_node_p_pos_chars node
|
|
|
|
size <- ts_node_p_size_chars node
|
|
|
|
return Range { start = fromEnum $ toInteger pos, end = (fromEnum $ toInteger pos) + (fromEnum $ toInteger size) }
|
|
|
|
|
2015-11-20 19:36:54 +03:00
|
|
|
files (a : as) = (a, file as) where
|
|
|
|
file (a : as) = a
|
2015-11-24 21:40:07 +03:00
|
|
|
files [] = error "expected two files to diff"
|