diff --git a/src/Data/Abstract/Evaluatable.hs b/src/Data/Abstract/Evaluatable.hs index 13e277f33..bb6034fc8 100644 --- a/src/Data/Abstract/Evaluatable.hs +++ b/src/Data/Abstract/Evaluatable.hs @@ -34,8 +34,6 @@ import Data.Abstract.Name as X import Data.Abstract.Package as Package import Data.Abstract.Ref as X import Data.Scientific (Scientific) -import Data.Semigroup.App -import Data.Semigroup.Foldable import Data.Semigroup.Reducer hiding (unit) import Data.Semilattice.Lower import Data.Sum @@ -217,11 +215,6 @@ instance Apply Evaluatable fs => Evaluatable (Sum fs) where instance Evaluatable s => Evaluatable (TermF s a) where eval = eval . termFOut --- | '[]' is treated as an imperative sequence of statements/declarations s.t.: --- --- 1. Each statement’s effects on the store are accumulated; --- 2. Each statement can affect the environment of later statements (e.g. by 'modify'-ing the environment); and --- 3. Only the last statement’s return value is returned. +-- | '[]' uses the default eval. Use Data.Syntax.Statements if you need an imperative sequence. instance Evaluatable [] where - -- 'nonEmpty' and 'foldMap1' enable us to return the last statement’s result instead of 'unit' for non-empty lists. - eval = maybe (pure (Rval unit)) (runApp . foldMap1 (App . subtermRef)) . nonEmpty + eval _ = throwResumable (Unspecialized ("Eval unspecialized for []")) diff --git a/src/Data/Syntax.hs b/src/Data/Syntax.hs index 2d5ea2f22..b5faf715d 100644 --- a/src/Data/Syntax.hs +++ b/src/Data/Syntax.hs @@ -30,12 +30,6 @@ makeTerm a = makeTerm' a . inject makeTerm' :: (HasCallStack, Semigroup a, Foldable f) => a -> f (Term f a) -> Term f a makeTerm' a f = termIn (sconcat (a :| (termAnnotation <$> toList f))) f --- | Lift syntax and an annotation into a term, injecting the syntax into a union & ensuring the annotation encompasses all children. Removes extra structure if term is a list of a single item. -makeTerm'' :: (HasCallStack, f :< fs, Semigroup a, Apply Foldable fs, Foldable f) => a -> f (Term (Sum fs) a) -> Term (Sum fs) a -makeTerm'' a children = case toList children of - [x] -> x - _ -> makeTerm' a (inject children) - -- | Lift non-empty syntax into a term, injecting the syntax into a union & appending all subterms’.annotations to make the new term’s annotation. makeTerm1 :: (HasCallStack, f :< fs, Semigroup a, Apply Foldable fs) => f (Term (Sum fs) a) -> Term (Sum fs) a makeTerm1 = makeTerm1' . inject @@ -46,11 +40,26 @@ makeTerm1' f = case toList f of a : _ -> makeTerm' (termAnnotation a) f _ -> error "makeTerm1': empty structure" +-- FIXME: I think this might be an anti-pattern. +-- | Lift syntax and an annotation into a term, injecting the syntax into a union & ensuring the annotation encompasses all children. Removes extra structure if term is a list of a single item. +makeStatementTerm :: (HasCallStack, f :< fs, Statements :< fs, Semigroup a, Apply Foldable fs, Foldable f) => a -> f (Term (Sum fs) a) -> Term (Sum fs) a +makeStatementTerm a children = case toList children of + [x] -> x + xs -> makeTerm' a (inject (Statements xs)) + -- | Construct an empty term at the current position. emptyTerm :: (HasCallStack, Empty :< fs, Apply Foldable fs) => Assignment.Assignment ast grammar (Term (Sum fs) (Record Location)) emptyTerm = makeTerm . startLocation <$> Assignment.location <*> pure Empty where startLocation ann = Range (start (getField ann)) (start (getField ann)) :. Span (spanStart (getField ann)) (spanStart (getField ann)) :. Nil +-- | Construct zero or more Statements. +manyStatements :: (Enum grammar, Eq1 ast, Ix grammar, Show grammar) => Assignment.Assignment ast grammar (Term f a) -> Assignment.Assignment ast grammar (Statements (Term f a)) +manyStatements expr = Exts.fromList <$> (many expr) + +-- | Construct an empty list of Statements. +emptyStatements :: Assignment.Assignment ast grammar (Statements (Term f a)) +emptyStatements = pure (Exts.fromList []) + -- | Catch assignment errors into an error term. handleError :: (HasCallStack, Error :< fs, Enum grammar, Eq1 ast, Ix grammar, Show grammar, Apply Foldable fs) => Assignment.Assignment ast grammar (Term (Sum fs) (Record Location)) -> Assignment.Assignment ast grammar (Term (Sum fs) (Record Location)) handleError = flip catchError (\ err -> makeTerm <$> Assignment.location <*> pure (errorSyntax (either id show <$> err) []) <* Assignment.source) @@ -132,6 +141,10 @@ instance Evaluatable Program where eval (Program statements) = eval statements -- | Imperative sequence of statements/declarations +-- +-- 1. Each statement’s effects on the store are accumulated; +-- 2. Each statement can affect the environment of later statements (e.g. by 'modify'-ing the environment); and +-- 3. Only the last statement’s return value is returned. newtype Statements a = Statements [a] deriving (Diffable, Eq, Foldable, Functor, Generic1, Hashable1, Mergeable, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1) @@ -140,6 +153,11 @@ instance Ord1 Statements where liftCompare = genericLiftCompare instance Show1 Statements where liftShowsPrec = genericLiftShowsPrec instance ToJSON1 Statements +-- | Imperative sequence of statements is evaluated s.t: +-- +-- 1. Each statement’s effects on the store are accumulated; +-- 2. Each statement can affect the environment of later statements (e.g. by 'modify'-ing the environment); and +-- 3. Only the last statement’s return value is returned. instance Evaluatable Statements where eval (Statements xs) = maybe (pure (Rval unit)) (runApp . foldMap1 (App . subtermRef)) (nonEmpty xs) @@ -148,6 +166,7 @@ instance Exts.IsList (Statements a) where fromList = Statements toList (Statements xs) = xs + -- | An accessibility modifier, e.g. private, public, protected, etc. newtype AccessibilityModifier a = AccessibilityModifier ByteString deriving (Diffable, Eq, Foldable, Functor, Generic1, Hashable1, Mergeable, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1) diff --git a/src/Language/Go/Assignment.hs b/src/Language/Go/Assignment.hs index cfcbc7795..778a7bb90 100644 --- a/src/Language/Go/Assignment.hs +++ b/src/Language/Go/Assignment.hs @@ -9,7 +9,7 @@ module Language.Go.Assignment import Assigning.Assignment hiding (Assignment, Error) import Data.Abstract.Name (name) import Data.Record -import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1) +import Data.Syntax (contextualize, emptyStatements, emptyTerm, handleError, infixContext, makeTerm, makeTerm', makeStatementTerm, makeTerm1, parseError) import Language.Go.Grammar as Grammar import Language.Go.Syntax as Go.Syntax import Language.Go.Type as Go.Type @@ -209,10 +209,10 @@ types = ] identifiers :: Assignment -identifiers = makeTerm'' <$> location <*> manyTerm identifier +identifiers = makeStatementTerm <$> location <*> manyTerm identifier expressions :: Assignment -expressions = makeTerm'' <$> location <*> manyTerm expression +expressions = makeStatementTerm <$> location <*> manyTerm expression -- Literals @@ -384,7 +384,7 @@ functionDeclaration = makeTerm <$> (symbol FunctionDeclaration <|> symbol FuncL returnParameters = makeTerm <$> symbol ParameterList <*> children (manyTerm expression) importDeclaration :: Assignment -importDeclaration = makeTerm'' <$> symbol ImportDeclaration <*> children (manyTerm (importSpec <|> importSpecList)) +importDeclaration = makeStatementTerm <$> symbol ImportDeclaration <*> children (manyTerm (importSpec <|> importSpecList)) where -- `import . "lib/Math"` dotImport = inject <$> (flip Go.Syntax.Import <$> dot <*> importFromPath) @@ -401,7 +401,7 @@ importDeclaration = makeTerm'' <$> symbol ImportDeclaration <*> children (manyTe dot = makeTerm <$> symbol Dot <*> (Literal.TextElement <$> source) underscore = makeTerm <$> symbol BlankIdentifier <*> (Literal.TextElement <$> source) importSpec = makeTerm' <$> symbol ImportSpec <*> children (sideEffectImport <|> dotImport <|> namedImport <|> plainImport) - importSpecList = makeTerm <$> symbol ImportSpecList <*> children (manyTerm (importSpec <|> comment)) + importSpecList = makeTerm <$> symbol ImportSpecList <*> children (manyStatements (importSpec <|> comment)) importFromPath = symbol InterpretedStringLiteral *> (importPath <$> source) indexExpression :: Assignment @@ -609,9 +609,6 @@ manyTerm = many . term manyStatements :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar (Syntax.Statements Term) manyStatements expr = fromList <$> (manyTerm expr) -emptyStatements :: Assignment.Assignment [] Grammar (Syntax.Statements Term) -emptyStatements = pure (fromList []) - -- | Match a term and contextualize any comments preceeding or proceeding the term. term :: Assignment -> Assignment term term' = contextualize comment term' <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm) diff --git a/src/Language/Haskell/Assignment.hs b/src/Language/Haskell/Assignment.hs index 0da96796c..5cd81ed5a 100644 --- a/src/Language/Haskell/Assignment.hs +++ b/src/Language/Haskell/Assignment.hs @@ -9,7 +9,7 @@ module Language.Haskell.Assignment import Assigning.Assignment hiding (Assignment, Error) import Data.Record import Data.Sum -import Data.Syntax (emptyTerm, handleError, parseError, makeTerm, makeTerm'', contextualize, postContextualize) +import Data.Syntax (emptyTerm, handleError, parseError, makeTerm, contextualize, postContextualize) import Language.Haskell.Grammar as Grammar import qualified Assigning.Assignment as Assignment import qualified Data.Abstract.Name as Name @@ -48,7 +48,7 @@ module' = makeTerm expressions :: Assignment -expressions = makeTerm'' <$> location <*> many expression +expressions = makeTerm <$> location <*> many expression expression :: Assignment expression = term (handleError (choice expressionChoices)) diff --git a/src/Language/PHP/Assignment.hs b/src/Language/PHP/Assignment.hs index 273503d64..83b68db38 100644 --- a/src/Language/PHP/Assignment.hs +++ b/src/Language/PHP/Assignment.hs @@ -117,6 +117,7 @@ type Syntax = '[ , Syntax.ScalarType , Syntax.ShellCommand , Syntax.SimpleVariable + , Syntax.Statements , Syntax.Static , Syntax.Text , Syntax.TraitDeclaration @@ -390,12 +391,12 @@ scalarType :: Assignment scalarType = makeTerm <$> symbol ScalarType <*> (Syntax.ScalarType <$> source) compoundStatement :: Assignment -compoundStatement = makeTerm <$> symbol CompoundStatement <*> children (manyTerm statement) +compoundStatement = makeTerm <$> symbol CompoundStatement <*> children (manyStatements statement) objectCreationExpression :: Assignment objectCreationExpression = (makeTerm <$> symbol ObjectCreationExpression <*> children (Expression.New <$> ((:) <$> term classTypeDesignator <*> (arguments <|> pure [])))) - <|> (makeTerm <$> symbol ObjectCreationExpression <*> children (makeAnonClass <$ token AnonNew <* token AnonClass <*> emptyTerm <*> (arguments <|> pure []) <*> (term classBaseClause <|> emptyTerm) <*> (term classInterfaceClause <|> emptyTerm) <*> (makeTerm <$> location <*> manyTerm classMemberDeclaration))) + <|> (makeTerm <$> symbol ObjectCreationExpression <*> children (makeAnonClass <$ token AnonNew <* token AnonClass <*> emptyTerm <*> (arguments <|> pure []) <*> (term classBaseClause <|> emptyTerm) <*> (term classInterfaceClause <|> emptyTerm) <*> (makeTerm <$> location <*> manyStatements classMemberDeclaration))) where makeAnonClass identifier args baseClause interfaceClause declarations = Declaration.Class [] identifier (args <> [baseClause, interfaceClause]) declarations classMemberDeclaration :: Assignment @@ -602,7 +603,7 @@ functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children (makeFu makeFunction identifier parameters returnType statement = Declaration.Function [returnType] identifier parameters statement classDeclaration :: Assignment -classDeclaration = makeTerm <$> symbol ClassDeclaration <*> children (makeClass <$> (term classModifier <|> emptyTerm) <*> term name <*> (term classBaseClause <|> emptyTerm) <*> (term classInterfaceClause <|> emptyTerm) <*> (makeTerm <$> location <*> manyTerm classMemberDeclaration)) +classDeclaration = makeTerm <$> symbol ClassDeclaration <*> children (makeClass <$> (term classModifier <|> emptyTerm) <*> term name <*> (term classBaseClause <|> emptyTerm) <*> (term classInterfaceClause <|> emptyTerm) <*> (makeTerm <$> location <*> manyStatements classMemberDeclaration)) where makeClass modifier name baseClause interfaceClause declarations = Declaration.Class [modifier] name [baseClause, interfaceClause] declarations @@ -734,7 +735,7 @@ functionStaticDeclaration :: Assignment functionStaticDeclaration = makeTerm <$> symbol FunctionStaticDeclaration <*> children (Declaration.VariableDeclaration <$> manyTerm staticVariableDeclaration) staticVariableDeclaration :: Assignment -staticVariableDeclaration = makeTerm <$> symbol StaticVariableDeclaration <*> children (Statement.Assignment <$> pure [] <*> term variableName <*> (term expression <|> emptyTerm)) +staticVariableDeclaration = makeTerm <$> symbol StaticVariableDeclaration <*> children (Statement.Assignment [] <$> term variableName <*> (term expression <|> emptyTerm)) comment :: Assignment comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source) @@ -767,6 +768,9 @@ someTerm = fmap NonEmpty.toList . someTerm' someTerm' :: Assignment -> Assignment.Assignment [] Grammar (NonEmpty Term) someTerm' = NonEmpty.some1 . commentedTerm +manyStatements :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar (Syntax.Statements Term) +manyStatements expr = fromList <$> (manyTerm expr) + -- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. infixTerm :: Assignment -> Assignment diff --git a/src/Language/Python/Assignment.hs b/src/Language/Python/Assignment.hs index 4ad69e75a..8fbfd5e84 100644 --- a/src/Language/Python/Assignment.hs +++ b/src/Language/Python/Assignment.hs @@ -10,7 +10,7 @@ module Language.Python.Assignment import Assigning.Assignment hiding (Assignment, Error) import Data.Abstract.Name (name) import Data.Record -import Data.Syntax (contextualize, emptyTerm, handleError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1, parseError, postContextualize) +import Data.Syntax (contextualize, emptyTerm, handleError, infixContext, makeTerm, makeTerm', makeStatementTerm, makeTerm1, parseError, postContextualize) import GHC.Stack import Language.Python.Grammar as Grammar import Language.Python.Syntax as Python.Syntax @@ -82,6 +82,7 @@ type Syntax = , Syntax.Error , Syntax.Identifier , Syntax.Program + , Syntax.Statements , Type.Annotation , [] ] @@ -91,7 +92,7 @@ type Assignment = HasCallStack => Assignment.Assignment [] Grammar Term -- | Assignment from AST in Python's grammar onto a program in Python's syntax. assignment :: Assignment -assignment = handleError $ makeTerm <$> symbol Module <*> children (Syntax.Program <$> manyStatements expression) <|> parseError +assignment = handleError $ makeTerm <$> symbol Module <*> children (Syntax.Program . fromList <$> manyTerm expression) <|> parseError expression :: Assignment expression = handleError (choice expressionChoices) @@ -163,14 +164,15 @@ expressionChoices = , yield ] + expressions :: Assignment -expressions = makeTerm'' <$> location <*> manyTerm expression +expressions = makeStatementTerm <$> location <*> manyTerm expression expressionStatement :: Assignment -expressionStatement = makeTerm'' <$> symbol ExpressionStatement <*> children (someTerm expression) +expressionStatement = makeStatementTerm <$> symbol ExpressionStatement <*> children (someTerm expression) expressionList :: Assignment -expressionList = makeTerm'' <$> symbol ExpressionList <*> children (someTerm expression) +expressionList = makeStatementTerm <$> symbol ExpressionList <*> children (someTerm expression) listSplat :: Assignment listSplat = makeTerm <$> symbol ListSplat <*> (Syntax.Identifier . name <$> source) @@ -241,7 +243,7 @@ functionDefinition = makeFunctionDeclaration loc (functionName', functionParameters, ty, functionBody) = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function [] functionName' functionParameters functionBody) (fromMaybe (makeTerm loc Syntax.Empty) ty) classDefinition :: Assignment -classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> pure [] <*> term expression <*> argumentList <*> expressions) +classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class [] <$> term expression <*> argumentList <*> expressions) where argumentList = symbol ArgumentList *> children (manyTerm expression) <|> pure [] @@ -360,7 +362,7 @@ comment :: Assignment comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source) import' :: Assignment -import' = makeTerm'' <$> symbol ImportStatement <*> children (manyTerm (aliasedImport <|> plainImport)) +import' = makeStatementTerm <$> symbol ImportStatement <*> children (manyTerm (aliasedImport <|> plainImport)) <|> makeTerm <$> symbol ImportFromStatement <*> children (Python.Syntax.Import <$> importPath <*> (wildcard <|> some (aliasImportSymbol <|> importSymbol))) where -- `import a as b` @@ -385,7 +387,7 @@ import' = makeTerm'' <$> symbol ImportStatement <*> children (manyTerm (aliase makeNameAliasPair from Nothing = (from, from) assertStatement :: Assignment -assertStatement = makeTerm <$> symbol AssertStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) +assertStatement = makeTerm <$> symbol AssertStatement <*> children (Expression.Call [] <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) printStatement :: Assignment printStatement = do @@ -399,19 +401,19 @@ printStatement = do printCallTerm location identifier = makeTerm location <$> (Expression.Call [] identifier <$> manyTerm expression <*> emptyTerm) nonlocalStatement :: Assignment -nonlocalStatement = makeTerm <$> symbol NonlocalStatement <*> children (Expression.Call <$> pure [] <*> term (makeTerm <$> symbol AnonNonlocal <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) +nonlocalStatement = makeTerm <$> symbol NonlocalStatement <*> children (Expression.Call [] <$> term (makeTerm <$> symbol AnonNonlocal <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) globalStatement :: Assignment -globalStatement = makeTerm <$> symbol GlobalStatement <*> children (Expression.Call <$> pure [] <*> term (makeTerm <$> symbol AnonGlobal <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) +globalStatement = makeTerm <$> symbol GlobalStatement <*> children (Expression.Call [] <$> term (makeTerm <$> symbol AnonGlobal <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) await :: Assignment -await = makeTerm <$> symbol Await <*> children (Expression.Call <$> pure [] <*> term (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) +await = makeTerm <$> symbol Await <*> children (Expression.Call [] <$> term (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm) returnStatement :: Assignment returnStatement = makeTerm <$> symbol ReturnStatement <*> children (Statement.Return <$> term (expressionList <|> emptyTerm)) deleteStatement :: Assignment -deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.Call <$> pure [] <*> term deleteIdentifier <* symbol ExpressionList <*> children (manyTerm expression) <*> emptyTerm) +deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.Call [] <$> term deleteIdentifier <* symbol ExpressionList <*> children (manyTerm expression) <*> emptyTerm) where deleteIdentifier = makeTerm <$> symbol AnonDel <*> (Syntax.Identifier . name <$> source) raiseStatement :: Assignment @@ -423,7 +425,7 @@ ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> ter makeElif (loc, makeIf) rest = makeTerm loc (makeIf rest) execStatement :: Assignment -execStatement = makeTerm <$> symbol ExecStatement <*> children (Expression.Call <$> pure [] <*> term (makeTerm <$> location <*> (Syntax.Identifier . name <$> source)) <*> manyTerm (string <|> expression) <*> emptyTerm) +execStatement = makeTerm <$> symbol ExecStatement <*> children (Expression.Call [] <$> term (makeTerm <$> location <*> (Syntax.Identifier . name <$> source)) <*> manyTerm (string <|> expression) <*> emptyTerm) passStatement :: Assignment passStatement = makeTerm <$> symbol PassStatement <*> (Statement.NoOp <$> emptyTerm <* advance) @@ -447,7 +449,7 @@ slice = makeTerm <$> symbol Slice <*> children <*> (term expression <|> emptyTerm)) call :: Assignment -call = makeTerm <$> symbol Call <*> children (Expression.Call <$> pure [] <*> term (identifier <|> expression) <*> (symbol ArgumentList *> children (manyTerm expression) <|> someTerm comprehension) <*> emptyTerm) +call = makeTerm <$> symbol Call <*> children (Expression.Call [] <$> term (identifier <|> expression) <*> (symbol ArgumentList *> children (manyTerm expression) <|> someTerm comprehension) <*> emptyTerm) boolean :: Assignment boolean = makeTerm <$> token Grammar.True <*> pure Literal.true @@ -476,6 +478,7 @@ conditionalExpression = makeTerm <$> symbol ConditionalExpression <*> children ( -- Helpers + -- | Match a term optionally preceded by comment(s), or a sequence of comments if the term is not present. manyTerm :: Assignment -> Assignment.Assignment [] Grammar [Term] manyTerm term = many (contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm)) @@ -486,7 +489,6 @@ someTerm term = some (contextualize comment term <|> makeTerm1 <$> (Syntax.Conte term :: Assignment -> Assignment term term = contextualize comment (postContextualize comment term) - -- | Match a left-associated infix chain of terms, optionally followed by comments. Like 'chainl1' but assigning comment nodes automatically. chainl1Term :: Assignment -> Assignment.Assignment [] Grammar (Term -> Term -> Term) -> Assignment chainl1Term expr op = postContextualize (comment <|> symbol AnonLambda *> empty) expr `chainl1` op @@ -495,9 +497,6 @@ chainl1Term expr op = postContextualize (comment <|> symbol AnonLambda *> empty) manyTermsTill :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar [Term] manyTermsTill step end = manyTill (step <|> comment) end -manyStatements :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar (Syntax.Statements Term) -manyStatements expr = fromList <$> (manyTerm expr) - -- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. infixTerm :: HasCallStack => Assignment diff --git a/src/Language/Ruby/Assignment.hs b/src/Language/Ruby/Assignment.hs index 6eaf4fcdf..92c710d5b 100644 --- a/src/Language/Ruby/Assignment.hs +++ b/src/Language/Ruby/Assignment.hs @@ -10,7 +10,19 @@ import Assigning.Assignment hiding (Assignment, Error) import Data.Abstract.Name (name) import Data.List (elem) import Data.Record -import Data.Syntax (contextualize, postContextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1) +import Data.Syntax + ( contextualize + , emptyTerm + , handleError + , infixContext + , makeTerm + , makeTerm' + , makeTerm1 + , makeStatementTerm + , manyStatements + , parseError + , postContextualize + ) import Language.Ruby.Grammar as Grammar import qualified Assigning.Assignment as Assignment import Data.Sum @@ -146,10 +158,10 @@ expressionChoices = mk s construct = makeTerm <$> symbol s <*> children ((construct .) . fromMaybe <$> emptyTerm <*> optional (symbol ArgumentList *> children expressions)) expressions :: Assignment -expressions = makeTerm'' <$> location <*> many expression +expressions = makeStatementTerm <$> location <*> many expression parenthesizedExpressions :: Assignment -parenthesizedExpressions = makeTerm'' <$> symbol ParenthesizedStatements <*> children (many expression) +parenthesizedExpressions = makeTerm <$> symbol ParenthesizedStatements <*> children (manyStatements expression) withExtendedScope :: Assignment' a -> Assignment' a withExtendedScope inner = do @@ -262,9 +274,8 @@ parameter = postContextualize comment (term uncontextualizedParameter) optionalParameter = symbol OptionalParameter *> children (lhsIdent <* expression) method :: Assignment -method = makeTerm <$> symbol Method <*> (withNewScope . children) (Declaration.Method <$> pure [] <*> emptyTerm <*> methodSelector <*> params <*> expressions') +method = makeTerm <$> symbol Method <*> (withNewScope . children) (Declaration.Method <$> pure [] <*> emptyTerm <*> methodSelector <*> params <*> expressions) where params = symbol MethodParameters *> children (many parameter) <|> pure [] - expressions' = makeTerm <$> location <*> many expression singletonMethod :: Assignment singletonMethod = makeTerm <$> symbol SingletonMethod <*> (withNewScope . children) (Declaration.Method <$> pure [] <*> expression <*> methodSelector <*> params <*> expressions) @@ -493,11 +504,8 @@ term term = contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> som where heredocEnd = makeTerm <$> symbol HeredocEnd <*> (Literal.TextElement <$> source) -- | Match a series of terms or comments until a delimiter is matched. -manyTermsTill :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar [Term] -manyTermsTill step end = manyTill (step <|> comment) end - -manyStatements :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar (Syntax.Statements Term) -manyStatements expr = fromList <$> (many expr) +manyTermsTill :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar (Syntax.Statements Term) +manyTermsTill step end = fromList <$> manyTill (step <|> comment) end -- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. infixTerm :: HasCallStack diff --git a/src/Language/TypeScript/Assignment.hs b/src/Language/TypeScript/Assignment.hs index be5911e8f..b3e2f2784 100644 --- a/src/Language/TypeScript/Assignment.hs +++ b/src/Language/TypeScript/Assignment.hs @@ -11,7 +11,7 @@ import Data.Abstract.Name (name) import qualified Assigning.Assignment as Assignment import Data.Record import Data.Sum -import Data.Syntax (emptyTerm, handleError, parseError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1, contextualize, postContextualize) +import Data.Syntax (emptyTerm, emptyStatements, handleError, parseError, infixContext, makeTerm, makeTerm', makeStatementTerm, makeTerm1, contextualize, postContextualize) import qualified Data.Syntax as Syntax import qualified Data.Syntax.Comment as Comment import qualified Data.Syntax.Declaration as Declaration @@ -558,10 +558,10 @@ constructorTy :: Assignment constructorTy = makeTerm <$> symbol ConstructorType <*> children (TypeScript.Syntax.Constructor <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> term ty) statementBlock :: Assignment -statementBlock = makeTerm <$> symbol StatementBlock <*> children (manyTerm statement) +statementBlock = makeTerm <$> symbol StatementBlock <*> children (manyStatements statement) classBodyStatements :: Assignment -classBodyStatements = makeTerm'' <$> symbol ClassBody <*> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as ++ [b]) <$> manyTerm decorator <*> term (methodDefinition <|> publicFieldDefinition <|> methodSignature <|> indexSignature <|> abstractMethodSignature))) <*> many comment)) +classBodyStatements = makeStatementTerm <$> symbol ClassBody <*> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as ++ [b]) <$> manyTerm decorator <*> term (methodDefinition <|> publicFieldDefinition <|> methodSignature <|> indexSignature <|> abstractMethodSignature))) <*> many comment)) where contextualize' (cs, formalParams) = case nonEmpty cs of Just cs -> toList cs ++ formalParams @@ -863,9 +863,6 @@ manyTerm term = many (contextualize comment term <|> makeTerm1 <$> (Syntax.Conte manyStatements :: Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar (Syntax.Statements Term) manyStatements expr = fromList <$> (manyTerm expr) -emptyStatements :: Assignment.Assignment [] Grammar (Syntax.Statements Term) -emptyStatements = pure (fromList []) - term :: Assignment -> Assignment term term = contextualize comment (postContextualize comment term)