Refactor AST -> types/parser, extract Range/Printer

This commit is contained in:
Kirill Andreev 2020-04-30 17:58:35 +04:00
parent 017db45f8d
commit c603cd399d
No known key found for this signature in database
GPG Key ID: CF7DA79DE4785A47
8 changed files with 304 additions and 262 deletions

View File

@ -4,7 +4,7 @@ cabal-version: 1.12
-- --
-- see: https://github.com/sol/hpack -- see: https://github.com/sol/hpack
-- --
-- hash: 67ec249f56014b97ea36ef06bb0dad0986e0f632e7fe62dc4393a5a081cb0493 -- hash: f4f92cb29b0c7d516e57ceee58c9d82900fc41d82cf21f7aa033094288165072
name: squirrel name: squirrel
version: 0.0.0 version: 0.0.0
@ -13,8 +13,12 @@ build-type: Simple
library library
exposed-modules: exposed-modules:
AST AST
AST.Parser
AST.Types
Parser Parser
ParseTree ParseTree
PrettyPrint
Range
other-modules: other-modules:
Paths_squirrel Paths_squirrel
hs-source-dirs: hs-source-dirs:

View File

@ -1,237 +1,5 @@
{- annotate tree with ranges, add offsets to ranges, store verbatim in Wrong* -} module AST (module M) where
module AST where import AST.Types as M
import AST.Parser as M
import Control.Monad.State
import qualified Data.Text as Text
import Data.Text (Text)
import Data.Void
import Parser
import ParseTree
import Debug.Trace
type TODO = Text
data Contract info
= Contract info [Declaration info]
| WrongContract Error
deriving stock (Show)
instance Stubbed (Contract info) where stub = WrongContract
data Declaration info
= ValueDecl info (Binding info)
| WrongDecl Error
deriving stock (Show)
instance Stubbed (Declaration info) where stub = WrongDecl
data Binding info
= Irrefutable info (Pattern info) (Expr info)
| Function info Bool (Name info) [VarDecl info] (Type info) TODO
| WrongBinding Error
deriving stock (Show)
instance Stubbed (Binding info) where stub = WrongBinding
data VarDecl info
= Decl info (Mutable info) (Name info) (Type info)
| WrongVarDecl Error
deriving stock (Show)
instance Stubbed (VarDecl info) where stub = WrongVarDecl
data Mutable info
= Mutable info
| Immutable info
| WrongMutable Error
deriving stock (Show)
instance Stubbed (Mutable info) where stub = WrongMutable
data Type info
= TArrow info (Type info) (Type info)
| Record info [(Name info, Type info)]
| TVar info (Name info)
| Sum info [(Name info, [Type info])]
| Product info [Type info]
| TApply info (Name info) [Type info]
| WrongType Error
deriving stock (Show)
instance Stubbed (Type info) where stub = WrongType
data Expr info
= Let info [Declaration info] (Expr info)
| Apply info (Expr info) (Expr info)
| Constant info (Constant info)
| Ident info (QualifiedName info)
| WrongExpr Error
deriving stock (Show)
instance Stubbed (Expr info) where stub = WrongExpr
data Constant info
= Int info Int
| String info Text
| Float info Double
| Bytes info Text
| WrongConstant Error
deriving stock (Show)
instance Stubbed (Constant info) where stub = WrongConstant
data Pattern info
= IsConstr info (Name info) [Pattern info]
| IsConstant info (Constant info)
| IsVar info (Name info)
| WrongPattern Error
deriving stock (Show)
instance Stubbed (Pattern info) where stub = WrongPattern
data QualifiedName info = QualifiedName
{ source :: Name info
, path :: [Name info]
}
| WrongQualifiedName Error
deriving stock (Show)
instance Stubbed (QualifiedName info) where stub = WrongQualifiedName
data Name info = Name
{ info :: info
, raw :: Text
}
| WrongName Error
instance Stubbed (Name info) where stub = WrongName
instance Show (Name info) where
show = \case
Name _ raw -> Text.unpack raw
WrongName r -> "(Name? " ++ show r ++ ")"
name :: Parser (Name Range)
name = do
(raw, info) <- range (token "Name")
return Name {info, raw}
contract :: Parser (Contract Range)
contract = subtree "contract" do
(decls, info) <- range do
many "declaration" declaration
return (Contract info decls)
declaration :: Parser (Declaration Range)
declaration =
stubbed "declaration" do
field "declaration" do
(b, info) <- range binding
return (ValueDecl info b)
par x = do
consume "("
a <- x
consume ")"
return a
binding :: Parser (Binding Range)
binding = do
info <- getRange
"fun_decl" `subtree` do
recur <- optional do
field "recursive" do
token "recursive"
consume "function"
name <- stubbed "name" do
field "name" do
name
params <-
field "parameters" do
subtree "parameters" do
par do
many "param" do
notFollowedBy do
consumeOrDie ")"
stubbed "parameters" do
paramDecl
consume ":"
ty <-
stubbed "type" do
field "type" type_
consume "is"
expr <- stubbed "body" do
field "locals" anything
return (Function info (recur == Just "recursive") name params ty expr)
paramDecl :: Parser (VarDecl Range)
paramDecl = do
info <- getRange
"parameter" `field` do
subtree "param_decl" do
info' <- getRange
mutable <- do
traceM "paramDecl"
stubbed "access" do
"access" `subtree` do
traceM "paramDecl"
select
[ consume "var" >> return (Mutable info')
, consume "const" >> return (Immutable info')
]
name <-
stubbed "name" do
field "name" name
consume ":"
ty <-
stubbed "type" do
field "type" type_
return (Decl info mutable name ty)
newtype_ = do
type_
type_ :: Parser (Type Range)
type_ =
fun_type
where
fun_type :: Parser (Type Range)
fun_type = do
stubbed "type" do
subtree "fun_type" do
info <- getRange
domain <- stubbed "domain" do
field "domain" cartesian
codomain <- optional do
consume "->"
fun_type
return case codomain of
Just co -> TArrow info domain co
Nothing -> domain
cartesian = do
stubbed "cartesian" do
subtree "cartesian" do
info <- getRange
Product info <$> some "corety" do
field "element" do
core_type
core_type = do
info <- getRange
select
[ TVar info <$> typename
]
typename = name
tuple :: Text -> Parser a -> Parser [a]
tuple msg = par . some msg
example = "../../../src/test/contracts/address.ligo"

View File

@ -0,0 +1,131 @@
module AST.Parser where
import Data.Text (Text)
import AST.Types
import Parser
import Range
import Debug.Trace
name :: Parser (Name Range)
name = do
(raw, info) <- range (token "Name")
return Name {info, raw}
contract :: Parser (Contract Range)
contract = subtree "contract" do
(decls, info) <- range do
many "declaration" declaration
return (Contract info decls)
declaration :: Parser (Declaration Range)
declaration =
stubbed "declaration" do
field "declaration" do
(b, info) <- range binding
return (ValueDecl info b)
par x = do
consume "("
a <- x
consume ")"
return a
binding :: Parser (Binding Range)
binding = do
info <- getRange
"fun_decl" `subtree` do
recur <- optional do
field "recursive" do
token "recursive"
consume "function"
name <- stubbed "name" do
field "name" do
name
params <-
field "parameters" do
subtree "parameters" do
par do
many "param" do
notFollowedBy do
consumeOrDie ")"
stubbed "parameters" do
paramDecl
consume ":"
ty <-
stubbed "type" do
field "type" type_
consume "is"
expr <- stubbed "body" do
field "locals" anything
return (Function info (recur == Just "recursive") name params ty expr)
paramDecl :: Parser (VarDecl Range)
paramDecl = do
info <- getRange
"parameter" `field` do
subtree "param_decl" do
info' <- getRange
mutable <- do
traceM "paramDecl"
stubbed "access" do
"access" `subtree` do
traceM "paramDecl"
select
[ consume "var" >> return (Mutable info')
, consume "const" >> return (Immutable info')
]
name <-
stubbed "name" do
field "name" name
consume ":"
ty <-
stubbed "type" do
field "type" type_
return (Decl info mutable name ty)
newtype_ = do
type_
type_ :: Parser (Type Range)
type_ =
fun_type
where
fun_type :: Parser (Type Range)
fun_type = do
stubbed "type" do
subtree "fun_type" do
info <- getRange
domain <- stubbed "domain" do
field "domain" cartesian
codomain <- optional do
consume "->"
fun_type
return case codomain of
Just co -> TArrow info domain co
Nothing -> domain
cartesian = do
stubbed "cartesian" do
subtree "cartesian" do
info <- getRange
Product info <$> some "corety" do
field "element" do
core_type
core_type = do
info <- getRange
select
[ TVar info <$> typename
]
typename = name
tuple :: Text -> Parser a -> Parser [a]
tuple msg = par . some msg
example = "../../../src/test/contracts/address.ligo"

View File

@ -0,0 +1,117 @@
{- annotate tree with ranges, add offsets to ranges, store verbatim in Wrong* -}
module AST.Types where
import Control.Monad.State
import qualified Data.Text as Text
import Data.Text (Text)
import Data.Void
import Parser
import ParseTree
import Debug.Trace
type TODO = Text
data Contract info
= Contract info [Declaration info]
| WrongContract Error
deriving stock (Show)
instance Stubbed (Contract info) where stub = WrongContract
data Declaration info
= ValueDecl info (Binding info)
| WrongDecl Error
deriving stock (Show)
instance Stubbed (Declaration info) where stub = WrongDecl
data Binding info
= Irrefutable info (Pattern info) (Expr info)
| Function info Bool (Name info) [VarDecl info] (Type info) TODO
| WrongBinding Error
deriving stock (Show)
instance Stubbed (Binding info) where stub = WrongBinding
data VarDecl info
= Decl info (Mutable info) (Name info) (Type info)
| WrongVarDecl Error
deriving stock (Show)
instance Stubbed (VarDecl info) where stub = WrongVarDecl
data Mutable info
= Mutable info
| Immutable info
| WrongMutable Error
deriving stock (Show)
instance Stubbed (Mutable info) where stub = WrongMutable
data Type info
= TArrow info (Type info) (Type info)
| Record info [(Name info, Type info)]
| TVar info (Name info)
| Sum info [(Name info, [Type info])]
| Product info [Type info]
| TApply info (Name info) [Type info]
| WrongType Error
deriving stock (Show)
instance Stubbed (Type info) where stub = WrongType
data Expr info
= Let info [Declaration info] (Expr info)
| Apply info (Expr info) (Expr info)
| Constant info (Constant info)
| Ident info (QualifiedName info)
| WrongExpr Error
deriving stock (Show)
instance Stubbed (Expr info) where stub = WrongExpr
data Constant info
= Int info Int
| String info Text
| Float info Double
| Bytes info Text
| WrongConstant Error
deriving stock (Show)
instance Stubbed (Constant info) where stub = WrongConstant
data Pattern info
= IsConstr info (Name info) [Pattern info]
| IsConstant info (Constant info)
| IsVar info (Name info)
| WrongPattern Error
deriving stock (Show)
instance Stubbed (Pattern info) where stub = WrongPattern
data QualifiedName info = QualifiedName
{ source :: Name info
, path :: [Name info]
}
| WrongQualifiedName Error
deriving stock (Show)
instance Stubbed (QualifiedName info) where stub = WrongQualifiedName
data Name info = Name
{ info :: info
, raw :: Text
}
| WrongName Error
instance Stubbed (Name info) where stub = WrongName
instance Show (Name info) where
show = \case
Name _ raw -> Text.unpack raw
WrongName r -> "(Name? " ++ show r ++ ")"

View File

@ -29,6 +29,9 @@ import Text.PrettyPrint hiding ((<>))
import Paths_squirrel import Paths_squirrel
import Range
import PrettyPrint
-- import Debug.Trace -- import Debug.Trace
foreign import ccall unsafe tree_sitter_PascaLigo :: Ptr Language foreign import ccall unsafe tree_sitter_PascaLigo :: Ptr Language
@ -52,22 +55,13 @@ data ParseForest = Forest
} }
instance Show ParseTree where instance Show ParseTree where
show = show . ppTree show = show . pp
instance Show ParseForest where instance Show ParseForest where
show = show . vcat . map ppPair . pfGrove show = show . pp
data Range = Range instance Pretty ParseTree where
{ rStart :: (Int, Int) pp (ParseTree _ n _ _ (Range (sr, sc) (fr, fc)) forest) =
, rFinish :: (Int, Int)
}
deriving stock (Show)
diffRange :: Range -> Range -> Range
diffRange (Range ws wf) (Range ps _) = Range (max ws ps) wf
ppTree :: ParseTree -> Doc
ppTree (ParseTree _ n _ _ (Range (sr, sc) (fr, fc)) (Forest _ cs _)) =
parens parens
( hang ( hang
( quotes (text (Text.unpack n)) ( quotes (text (Text.unpack n))
@ -78,12 +72,16 @@ ppTree (ParseTree _ n _ _ (Range (sr, sc) (fr, fc)) (Forest _ cs _)) =
) )
) )
2 2
(vcat (map ppPair cs))) (pp forest)
)
ppPair (field, tree) = instance Pretty ParseForest where
pp = vcat . map ppPair . pfGrove
where
ppPair (field, tree) =
if field == Text.empty if field == Text.empty
then nest 2 $ ppTree tree then nest 2 $ pp tree
else hang (text (Text.unpack field) <> ": ") 2 (ppTree tree) else hang (text (Text.unpack field) <> ": ") 2 (pp tree)
toParseTree :: FilePath -> IO ParseForest toParseTree :: FilePath -> IO ParseForest
toParseTree fin = do toParseTree fin = do

View File

@ -14,6 +14,7 @@ import qualified Data.ByteString as ByteString
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import ParseTree import ParseTree
import Range
import Debug.Trace import Debug.Trace

View File

@ -0,0 +1,11 @@
module PrettyPrint
( module PrettyPrint
, module Text.PrettyPrint
)
where
import Text.PrettyPrint hiding ((<>))
class Pretty p where
pp :: p -> Doc

View File

@ -0,0 +1,12 @@
module Range where
data Range = Range
{ rStart :: (Int, Int)
, rFinish :: (Int, Int)
}
deriving stock (Show)
diffRange :: Range -> Range -> Range
diffRange (Range ws wf) (Range ps _) = Range (max ws ps) wf