1
1
mirror of https://github.com/github/semantic.git synced 2024-12-29 01:42:43 +03:00

Define type synonyms for Ruby and Python assignment so as to not have to keep editing every type signature.

This commit is contained in:
Rob Rix 2017-06-07 15:57:39 -04:00
parent 79724efd67
commit 40f86f4b59
2 changed files with 72 additions and 70 deletions

View File

@ -13,7 +13,7 @@ import Data.Functor.Classes.Show.Generic
import Data.Functor.Union
import Data.Record
import qualified Data.Syntax as Syntax
import Data.Syntax.Assignment hiding (Error)
import Data.Syntax.Assignment hiding (Assignment, Error)
import qualified Data.Syntax.Assignment as Assignment
import qualified Data.Syntax.Comment as Comment
import qualified Data.Syntax.Declaration as Declaration
@ -65,6 +65,7 @@ type Syntax =
type Error = Assignment.Error Grammar
type Term = Term.Term (Union Syntax) (Record Location)
type Assignment = Assignment.Assignment Grammar Term
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
data Ellipsis a = Ellipsis
@ -81,13 +82,13 @@ instance Eq1 Redirect where liftEq = genericLiftEq
instance Show1 Redirect where liftShowsPrec = genericLiftShowsPrec
-- | Assignment from AST in Python's grammar onto a program in Python's syntax.
assignment :: HasCallStack => Assignment Grammar Term
assignment :: HasCallStack => Assignment
assignment = makeTerm <$> symbol Module <*> children (many declaration)
declaration :: HasCallStack => Assignment Grammar Term
declaration :: HasCallStack => Assignment
declaration = handleError $ comment <|> statement <|> expression
statement :: HasCallStack => Assignment Grammar Term
statement :: HasCallStack => Assignment
statement = assertStatement
<|> assignment'
<|> augmentedAssignment
@ -100,10 +101,10 @@ statement = assertStatement
<|> printStatement
<|> returnStatement
expressionStatement :: HasCallStack => Assignment Grammar Term
expressionStatement :: HasCallStack => Assignment
expressionStatement = symbol ExpressionStatement *> children expression
expression :: HasCallStack => Assignment Grammar Term
expression :: HasCallStack => Assignment
expression = await
<|> binaryOperator
<|> booleanOperator
@ -123,13 +124,13 @@ expression = await
<|> tuple
<|> unaryOperator
dottedName :: HasCallStack => Assignment Grammar Term
dottedName :: HasCallStack => Assignment
dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression)
ellipsis :: HasCallStack => Assignment Grammar Term
ellipsis :: HasCallStack => Assignment
ellipsis = makeTerm <$> symbol Grammar.Ellipsis <*> (Language.Python.Syntax.Ellipsis <$ source)
comparisonOperator :: HasCallStack => Assignment Grammar Term
comparisonOperator :: HasCallStack => Assignment
comparisonOperator = symbol ComparisonOperator >>= \ loc -> children (expression >>= \ lexpression -> makeComparison loc lexpression)
where
makeComparison loc lexpression = makeTerm loc <$ symbol AnonLAngle <*> (Expression.LessThan lexpression <$> expression)
@ -144,26 +145,26 @@ comparisonOperator = symbol ComparisonOperator >>= \ loc -> children (expression
<|> symbol AnonIs *> source *> (symbol AnonNot *> (makeTerm loc <$> Expression.Not <$> (makeTerm <$> location <*> (Expression.Equal lexpression <$> expression)))
<|> (makeTerm loc <$> Expression.Equal lexpression <$> expression))
notOperator :: HasCallStack => Assignment Grammar Term
notOperator :: HasCallStack => Assignment
notOperator = makeTerm <$> symbol NotOperator <*> children (Expression.Not <$> expression)
keywordIdentifier :: HasCallStack => Assignment Grammar Term
keywordIdentifier :: HasCallStack => Assignment
keywordIdentifier = makeTerm <$> symbol KeywordIdentifier <*> children (Syntax.Identifier <$> source)
tuple :: HasCallStack => Assignment Grammar Term
tuple :: HasCallStack => Assignment
tuple = makeTerm <$> symbol Tuple <*> children (Literal.Tuple <$> (many expression))
-- TODO: Consider flattening single element lists
expressionList :: HasCallStack => Assignment Grammar Term
expressionList :: HasCallStack => Assignment
expressionList = makeTerm <$> symbol ExpressionList <*> children (many expression)
unaryOperator :: HasCallStack => Assignment Grammar Term
unaryOperator :: HasCallStack => Assignment
unaryOperator = symbol UnaryOperator >>= \ location -> arithmetic location <|> bitwise location <|> children ( symbol AnonPlus *> expression )
where
arithmetic location = makeTerm location . Expression.Negate <$> children ( symbol AnonMinus *> expression )
bitwise location = makeTerm location . Expression.Complement <$> children ( symbol AnonTilde *> expression )
binaryOperator :: HasCallStack => Assignment Grammar Term
binaryOperator :: HasCallStack => Assignment
binaryOperator = symbol BinaryOperator >>= \ location -> children (expression >>= \ lexpression ->
makeTerm location <$> arithmetic lexpression
<|> makeTerm location <$> bitwise lexpression)
@ -181,17 +182,17 @@ binaryOperator = symbol BinaryOperator >>= \ location -> children (expression >>
<|> symbol AnonLAngleLAngle *> (Expression.LShift lexpression <$> expression)
<|> symbol AnonRAngleRAngle *> (Expression.RShift lexpression <$> expression)
booleanOperator :: HasCallStack => Assignment Grammar Term
booleanOperator :: HasCallStack => Assignment
booleanOperator = makeTerm <$> symbol BooleanOperator <*> children ( expression >>= booleanOperator' )
where
booleanOperator' lexpression = symbol AnonAnd *> (Expression.And lexpression <$> expression)
<|> symbol AnonOr *> (Expression.Or lexpression <$> expression)
assignment' :: HasCallStack => Assignment Grammar Term
assignment' :: HasCallStack => Assignment
assignment' =
makeTerm <$> symbol Assignment <*> children (Statement.Assignment <$> expressionList <*> rvalue)
augmentedAssignment :: HasCallStack => Assignment Grammar Term
augmentedAssignment :: HasCallStack => Assignment
augmentedAssignment = makeTerm <$> symbol AugmentedAssignment <*> children (expressionList >>= \ lvalue -> Statement.Assignment lvalue <$>
(makeTerm <$> symbol AnonPlusEqual <*> (Expression.Plus lvalue <$> rvalue)
<|> makeTerm <$> symbol AnonMinusEqual <*> (Expression.Minus lvalue <$> rvalue)
@ -206,56 +207,56 @@ augmentedAssignment = makeTerm <$> symbol AugmentedAssignment <*> children (expr
<|> makeTerm <$> symbol AnonLAngleLAngleEqual <*> (Expression.LShift lvalue <$> rvalue)
<|> makeTerm <$> symbol AnonCaretEqual <*> (Expression.BXOr lvalue <$> rvalue)))
yield :: HasCallStack => Assignment Grammar Term
yield :: HasCallStack => Assignment
yield = makeTerm <$> symbol Yield <*> (Statement.Yield <$> children ( expression <|> expressionList <|> emptyTerm ))
rvalue :: HasCallStack => Assignment Grammar Term
rvalue :: HasCallStack => Assignment
rvalue = expressionList <|> assignment' <|> augmentedAssignment <|> yield
identifier :: HasCallStack => Assignment Grammar Term
identifier :: HasCallStack => Assignment
identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier <$> source)
literal :: HasCallStack => Assignment Grammar Term
literal :: HasCallStack => Assignment
literal = string <|> integer <|> float <|> boolean <|> none <|> concatenatedString <|> list' <|> dictionary <|> set
set :: HasCallStack => Assignment Grammar Term
set :: HasCallStack => Assignment
set = makeTerm <$> symbol Set <*> children (Literal.Set <$> many expression)
dictionary :: HasCallStack => Assignment Grammar Term
dictionary :: HasCallStack => Assignment
dictionary = makeTerm <$> symbol Dictionary <*> children (Literal.Hash <$> many pairs)
where pairs = makeTerm <$> symbol Pair <*> children (Literal.KeyValue <$> expression <*> expression)
list' :: HasCallStack => Assignment Grammar Term
list' :: HasCallStack => Assignment
list' = makeTerm <$> symbol List <*> children (Literal.Array <$> many expression)
-- TODO: Wrap `Literal.TextElement` with a `Literal.String`
string :: HasCallStack => Assignment Grammar Term
string :: HasCallStack => Assignment
string = makeTerm <$> symbol String <*> (Literal.TextElement <$> source)
concatenatedString :: HasCallStack => Assignment Grammar Term
concatenatedString :: HasCallStack => Assignment
concatenatedString = makeTerm <$> symbol ConcatenatedString <*> children (Literal.TextElement . mconcat <$> many (symbol String *> source))
float :: HasCallStack => Assignment Grammar Term
float :: HasCallStack => Assignment
float = makeTerm <$> symbol Float <*> (Literal.Float <$> source)
integer :: HasCallStack => Assignment Grammar Term
integer :: HasCallStack => Assignment
integer = makeTerm <$> symbol Integer <*> (Literal.Integer <$> source)
comment :: HasCallStack => Assignment Grammar Term
comment :: HasCallStack => Assignment
comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source)
-- TODO Possibly match against children for dotted name and identifiers
import' :: HasCallStack => Assignment Grammar Term
import' :: HasCallStack => Assignment
import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import <$> many expression)
-- TODO Possibly match against children nodes
importFrom :: HasCallStack => Assignment Grammar Term
importFrom :: HasCallStack => Assignment
importFrom = makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression)
assertStatement :: HasCallStack => Assignment Grammar Term
assertStatement :: HasCallStack => Assignment
assertStatement = makeTerm <$ symbol AssertStatement <*> location <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression)
printStatement :: HasCallStack => Assignment Grammar Term
printStatement :: HasCallStack => Assignment
printStatement = do
location <- symbol PrintStatement
children $ do
@ -266,47 +267,47 @@ printStatement = do
redirectCallTerm location keyword = makeTerm location <$ symbol Chevron <*> (flip Redirect <$> children expression <*> printCallTerm location keyword)
printCallTerm location keyword = makeTerm location . Expression.Call keyword <$> many expression
globalStatement :: HasCallStack => Assignment Grammar Term
globalStatement :: HasCallStack => Assignment
globalStatement = makeTerm <$> symbol GlobalStatement <*> children (Expression.Call <$> (makeTerm <$> symbol AnonGlobal <*> (Syntax.Identifier <$> source)) <*> many identifier)
await :: HasCallStack => Assignment Grammar Term
await :: HasCallStack => Assignment
await = makeTerm <$> symbol Await <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier <$> source)) <*> many expression)
returnStatement :: HasCallStack => Assignment Grammar Term
returnStatement :: HasCallStack => Assignment
returnStatement = makeTerm <$> symbol ReturnStatement <*> (Statement.Return <$> children expressionList)
ifStatement :: HasCallStack => Assignment Grammar Term
ifStatement :: HasCallStack => Assignment
ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> statement <*> (flip (foldr makeElif) <$> many elifClause <*> optionalElse))
where elseClause = symbol ElseClause *> children statement
elifClause = (,) <$ symbol ElifClause <*> location <*> children (Statement.If <$> expression <*> statement)
optionalElse = fromMaybe <$> emptyTerm <*> optional elseClause
makeElif (loc, makeIf) rest = makeTerm loc (makeIf rest)
memberAccess :: HasCallStack => Assignment Grammar Term
memberAccess :: HasCallStack => Assignment
memberAccess = makeTerm <$> symbol Attribute <*> children (Expression.MemberAccess <$> expression <*> expression)
subscript :: HasCallStack => Assignment Grammar Term
subscript :: HasCallStack => Assignment
subscript = makeTerm <$> symbol Subscript <*> children (Expression.Subscript <$> expression <*> many expression)
call :: HasCallStack => Assignment Grammar Term
call :: HasCallStack => Assignment
call = makeTerm <$> symbol Call <*> children (Expression.Call <$> identifier <*> (symbol ArgumentList *> children (many expression)
<|> some comprehension))
boolean :: HasCallStack => Assignment Grammar Term
boolean :: HasCallStack => Assignment
boolean = makeTerm <$> symbol Grammar.True <*> (Literal.true <$ source)
<|> makeTerm <$> symbol Grammar.False <*> (Literal.false <$ source)
none :: HasCallStack => Assignment Grammar Term
none :: HasCallStack => Assignment
none = makeTerm <$> symbol None <*> (Literal.Null <$ source)
lambda :: HasCallStack => Assignment Grammar Term
lambda :: HasCallStack => Assignment
lambda = makeTerm <$> symbol Lambda <*> children (Declaration.Function <$> lambdaIdentifier <*> lambdaParameters <*> lambdaBody)
where lambdaIdentifier = makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source)
lambdaParameters = many identifier
lambdaBody = expression
comprehension :: HasCallStack => Assignment Grammar Term
comprehension :: HasCallStack => Assignment
comprehension = makeTerm <$> symbol GeneratorExpression <*> children (comprehensionDeclaration expression)
<|> makeTerm <$> symbol ListComprehension <*> children (comprehensionDeclaration expression)
<|> makeTerm <$> symbol SetComprehension <*> children (comprehensionDeclaration expression)
@ -317,16 +318,16 @@ comprehension = makeTerm <$> symbol GeneratorExpression <*> children (comprehen
makeComprehension (loc, makeRest) rest = makeTerm loc (makeRest rest)
nestedComprehension = (,) <$> location <*> (Declaration.Comprehension <$> expression <* symbol Variables <*> children (many expression))
conditionalExpression :: HasCallStack => Assignment Grammar Term
conditionalExpression :: HasCallStack => Assignment
conditionalExpression = makeTerm <$> symbol ConditionalExpression <*> children (expression >>= \ thenBranch -> expression >>= \ conditional -> Statement.If conditional thenBranch <$> (expression <|> emptyTerm))
makeTerm :: (HasCallStack, InUnion fs f) => a -> f (Term.Term (Union fs) a) -> Term.Term (Union fs) a
makeTerm a f = cofree (a :< inj f)
emptyTerm :: HasCallStack => Assignment Grammar Term
emptyTerm :: HasCallStack => Assignment
emptyTerm = makeTerm <$> location <*> pure Syntax.Empty
handleError :: HasCallStack => Assignment Grammar Term -> Assignment Grammar Term
handleError :: HasCallStack => Assignment -> Assignment
handleError = flip catchError $ \ error -> case errorCause error of
UnexpectedEndOfInput _ -> throwError error
_ -> makeTerm <$> location <*> (Syntax.Error error <$ source)

View File

@ -10,7 +10,7 @@ module Language.Ruby.Syntax
import Data.Functor.Union
import Data.Record
import qualified Data.Syntax as Syntax
import Data.Syntax.Assignment hiding (Error)
import Data.Syntax.Assignment hiding (Assignment, Error)
import qualified Data.Syntax.Assignment as Assignment
import qualified Data.Syntax.Comment as Comment
import qualified Data.Syntax.Declaration as Declaration
@ -55,33 +55,34 @@ type Syntax =
type Error = Assignment.Error Grammar
type Term = Term.Term (Union Syntax) (Record Location)
type Assignment = Assignment.Assignment Grammar Term
-- | Assignment from AST in Rubys grammar onto a program in Rubys syntax.
assignment :: HasCallStack => Assignment Grammar Term
assignment :: HasCallStack => Assignment
assignment = makeTerm <$> symbol Program <*> children (many declaration)
declaration :: HasCallStack => Assignment Grammar Term
declaration :: HasCallStack => Assignment
declaration = handleError $ comment <|> class' <|> method
class' :: HasCallStack => Assignment Grammar Term
class' :: HasCallStack => Assignment
class' = makeTerm <$> symbol Class <*> children (Declaration.Class <$> (constant <|> scopeResolution) <*> (superclass <|> pure []) <*> many declaration)
where superclass = pure <$ symbol Superclass <*> children constant
scopeResolution = symbol ScopeResolution *> children (constant <|> identifier)
constant :: HasCallStack => Assignment Grammar Term
constant :: HasCallStack => Assignment
constant = makeTerm <$> symbol Constant <*> (Syntax.Identifier <$> source)
identifier :: HasCallStack => Assignment Grammar Term
identifier :: HasCallStack => Assignment
identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier <$> source)
method :: HasCallStack => Assignment Grammar Term
method :: HasCallStack => Assignment
method = makeTerm <$> symbol Method <*> children (Declaration.Method <$> identifier <*> pure [] <*> statements)
statements :: HasCallStack => Assignment Grammar Term
statements :: HasCallStack => Assignment
statements = makeTerm <$> location <*> many statement
statement :: HasCallStack => Assignment Grammar Term
statement :: HasCallStack => Assignment
statement = handleError
$ exit Statement.Return Return
<|> exit Statement.Yield Yield
@ -96,36 +97,36 @@ statement = handleError
<|> assignment'
where exit construct sym = makeTerm <$> symbol sym <*> children ((construct .) . fromMaybe <$> emptyTerm <*> optional (symbol ArgumentList *> children statement))
lvalue :: HasCallStack => Assignment Grammar Term
lvalue :: HasCallStack => Assignment
lvalue = identifier
expression :: HasCallStack => Assignment Grammar Term
expression :: HasCallStack => Assignment
expression = identifier <|> statement
comment :: HasCallStack => Assignment Grammar Term
comment :: HasCallStack => Assignment
comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source)
if' :: HasCallStack => Assignment Grammar Term
if' :: HasCallStack => Assignment
if' = ifElsif If
<|> makeTerm <$> symbol IfModifier <*> children (flip Statement.If <$> statement <*> statement <*> (makeTerm <$> location <*> pure Syntax.Empty))
where ifElsif s = makeTerm <$> symbol s <*> children (Statement.If <$> statement <*> statements <*> (fromMaybe <$> emptyTerm <*> optional (ifElsif Elsif <|> makeTerm <$> symbol Else <*> children (many statement))))
unless :: HasCallStack => Assignment Grammar Term
unless :: HasCallStack => Assignment
unless = makeTerm <$> symbol Unless <*> children (Statement.If <$> invert statement <*> statements <*> (fromMaybe <$> emptyTerm <*> optional (makeTerm <$> symbol Else <*> children (many statement))))
<|> makeTerm <$> symbol UnlessModifier <*> children (flip Statement.If <$> statement <*> invert statement <*> (makeTerm <$> location <*> pure Syntax.Empty))
while :: HasCallStack => Assignment Grammar Term
while :: HasCallStack => Assignment
while = makeTerm <$> symbol While <*> children (Statement.While <$> statement <*> statements)
<|> makeTerm <$> symbol WhileModifier <*> children (flip Statement.While <$> statement <*> statement)
until :: HasCallStack => Assignment Grammar Term
until :: HasCallStack => Assignment
until = makeTerm <$> symbol Until <*> children (Statement.While <$> invert statement <*> statements)
<|> makeTerm <$> symbol UntilModifier <*> children (flip Statement.While <$> statement <*> invert statement)
for :: HasCallStack => Assignment Grammar Term
for :: HasCallStack => Assignment
for = makeTerm <$> symbol For <*> children (Statement.ForEach <$> identifier <*> statement <*> statements)
assignment' :: HasCallStack => Assignment Grammar Term
assignment' :: HasCallStack => Assignment
assignment'
= makeTerm <$> symbol Assignment <*> children (Statement.Assignment <$> lvalue <*> expression)
<|> makeTerm <$> symbol OperatorAssignment <*> children (lvalue >>= \ var -> Statement.Assignment var <$>
@ -143,23 +144,23 @@ assignment'
<|> makeTerm <$> symbol AnonLAngleLAngleEqual <*> (Expression.LShift var <$> expression)
<|> makeTerm <$> symbol AnonCaretEqual <*> (Expression.BXOr var <$> expression)))
literal :: HasCallStack => Assignment Grammar Term
literal :: HasCallStack => Assignment
literal = makeTerm <$> symbol Grammar.True <*> (Literal.true <$ source)
<|> makeTerm <$> symbol Grammar.False <*> (Literal.false <$ source)
<|> makeTerm <$> symbol Grammar.Integer <*> (Literal.Integer <$> source)
<|> makeTerm <$> symbol Symbol <*> (Literal.Symbol <$> source)
<|> makeTerm <$> symbol Range <*> children (Literal.Range <$> statement <*> statement) -- FIXME: represent the difference between .. and ...
invert :: (InUnion fs Expression.Boolean, HasCallStack) => Assignment grammar (Term.Term (Union fs) (Record Location)) -> Assignment grammar (Term.Term (Union fs) (Record Location))
invert :: (InUnion fs Expression.Boolean, HasCallStack) => Assignment.Assignment grammar (Term.Term (Union fs) (Record Location)) -> Assignment.Assignment grammar (Term.Term (Union fs) (Record Location))
invert term = makeTerm <$> location <*> fmap Expression.Not term
makeTerm :: (InUnion fs f, HasCallStack) => a -> f (Term.Term (Union fs) a) -> Term.Term (Union fs) a
makeTerm a f = cofree $ a :< inj f
emptyTerm :: HasCallStack => Assignment Grammar Term
emptyTerm :: HasCallStack => Assignment
emptyTerm = makeTerm <$> location <*> pure Syntax.Empty
handleError :: HasCallStack => Assignment Grammar Term -> Assignment Grammar Term
handleError :: HasCallStack => Assignment -> Assignment
handleError = flip catchError $ \ error -> case errorCause error of
UnexpectedEndOfInput _ -> throwError error
_ -> makeTerm <$> location <*> (Syntax.Error error <$ source)