From 8fc65cbee2639fec5c4223c05583e7d71cbb07d9 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 12:25:34 -0700 Subject: [PATCH 01/12] Properly assign binary - and * --- src/Language/Ruby/Syntax.hs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index 94f557482..c59d14777 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -379,11 +379,8 @@ binary = symbol Binary >>= \ loc -> children $ (expression <|> emptyTerm) >>= \ <|> mk AnonSlash Expression.DividedBy <|> mk AnonPercent Expression.Modulo <|> mk AnonStarStar Expression.Power - -- TODO: binary minus and binary star (hidden nodes). Doesn't work b/c we - -- can't match hidden nodes (they aren't in the tree). - -- <|> mk HiddenBinaryMinus Expression.Minus - -- FIXME: This falls through to always assign binary as minus, which isn't correct. - <|> makeTerm loc <$> (Expression.Minus lexpression <$> (expression <|> emptyTerm)) + <|> mk AnonMinus' Expression.Minus + <|> mk AnonStar' Expression.Times where mk s constr = makeTerm loc <$> (symbol s *> (constr lexpression <$> expression)) mkNot s constr = makeTerm loc <$ symbol s <*> (Expression.Not <$> (makeTerm <$> location <*> (constr lexpression <$> expression))) From f0e96bc9477d0767bf0a2656bce5077c2ac1e6ee Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 13:30:13 -0700 Subject: [PATCH 02/12] Add in comment handling, re-write binary Also add complex and rational literals --- src/Language/Ruby/Syntax.hs | 113 ++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index c59d14777..a0828f48e 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE DataKinds, RankNTypes, TypeOperators #-} +{-# LANGUAGE DataKinds, DeriveAnyClass, RankNTypes, TypeOperators #-} module Language.Ruby.Syntax ( assignment , Syntax @@ -6,10 +6,16 @@ module Language.Ruby.Syntax , Term ) where +import Algorithm +import Data.Align.Generic +import Data.ByteString import Data.Maybe (fromMaybe) import Data.Record import Data.Functor (void) -import Data.Syntax (emptyTerm, makeTerm, parseError, handleError) +import Data.Functor.Classes.Eq.Generic +import Data.Functor.Classes.Show.Generic +import Data.List.NonEmpty (some1) +import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm1, postContextualize) import qualified Data.Syntax as Syntax import Data.Syntax.Assignment hiding (Assignment, Error) import qualified Data.Syntax.Assignment as Assignment @@ -19,6 +25,7 @@ import qualified Data.Syntax.Expression as Expression import qualified Data.Syntax.Literal as Literal import qualified Data.Syntax.Statement as Statement import Data.Union +import GHC.Generics import GHC.Stack import Language.Ruby.Grammar as Grammar import qualified Term @@ -39,6 +46,8 @@ type Syntax = '[ , Expression.MemberAccess , Expression.ScopeResolution , Expression.Subscript + , Language.Ruby.Syntax.Rational + , Language.Ruby.Syntax.Complex , Literal.Array , Literal.Boolean , Literal.Float @@ -66,6 +75,7 @@ type Syntax = '[ , Statement.Try , Statement.While , Statement.Yield + , Syntax.Context , Syntax.Empty , Syntax.Error , Syntax.Identifier @@ -76,13 +86,26 @@ type Syntax = '[ type Term = Term.Term (Union Syntax) (Record Location) type Assignment = HasCallStack => Assignment.Assignment (AST Grammar) Grammar Term +-- Rational literal e.g. `2/3r` +newtype Rational a = Rational ByteString + deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Language.Ruby.Syntax.Rational where liftEq = genericLiftEq +instance Show1 Language.Ruby.Syntax.Rational where liftShowsPrec = genericLiftShowsPrec + +newtype Complex a = Complex ByteString + deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Language.Ruby.Syntax.Complex where liftEq = genericLiftEq +instance Show1 Language.Ruby.Syntax.Complex where liftShowsPrec = genericLiftShowsPrec + -- | Assignment from AST in Ruby’s grammar onto a program in Ruby’s syntax. assignment :: Assignment assignment = handleError $ makeTerm <$> symbol Program <*> children (Syntax.Program <$> many expression) expression :: Assignment -expression = handleError $ +expression = handleError . term $ alias <|> assignment' <|> begin @@ -92,7 +115,6 @@ expression = handleError $ <|> call <|> case' <|> class' - <|> comment <|> conditional <|> emptyStatement <|> endBlock @@ -154,15 +176,17 @@ identifier = literal :: 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 Grammar.Float <*> (Literal.Float <$> source) - <|> makeTerm <$> symbol Grammar.Nil <*> (Literal.Null <$ source) + makeTerm <$> symbol Grammar.True <*> (Literal.true <$ source) + <|> makeTerm <$> symbol Grammar.False <*> (Literal.false <$ source) + <|> makeTerm <$> symbol Grammar.Integer <*> (Literal.Integer <$> source) + <|> makeTerm <$> symbol Grammar.Float <*> (Literal.Float <$> source) + <|> makeTerm <$> symbol Grammar.Nil <*> (Literal.Null <$ source) + <|> makeTerm <$> symbol Grammar.Rational <*> (Language.Ruby.Syntax.Rational <$> source) + <|> makeTerm <$> symbol Grammar.Complex <*> (Language.Ruby.Syntax.Complex <$> source) -- TODO: Do we want to represent the difference between .. and ... <|> makeTerm <$> symbol Range <*> children (Expression.Enumeration <$> expression <*> expression <*> emptyTerm) <|> makeTerm <$> symbol Array <*> children (Literal.Array <$> many expression) - <|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> many pair) + <|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> many pair) -- TODO: Give subshell it's own literal and allow interpolation <|> makeTerm <$> symbol Subshell <*> (Literal.TextElement <$> source) -- TODO: Handle interpolation @@ -350,39 +374,32 @@ unary = symbol Unary >>= \ location -> <|> makeTerm location . Expression.Negate <$> children ( symbol AnonMinus' *> expression ) <|> children ( symbol AnonPlus *> expression ) +-- TODO: Distinguish `===` from `==` ? +-- TODO: Distinuish `=~` and `!~` ? binary :: Assignment -binary = symbol Binary >>= \ loc -> children $ (expression <|> emptyTerm) >>= \ lexpression -> go loc lexpression - where - go loc lexpression - = mk AnonAnd Expression.And - <|> mk AnonAmpersandAmpersand Expression.And - <|> mk AnonOr Expression.Or - <|> mk AnonPipePipe Expression.Or - <|> mk AnonLAngleLAngle Expression.LShift - <|> mk AnonRAngleRAngle Expression.RShift - <|> mk AnonEqualEqual Expression.Equal - <|> mkNot AnonBangEqual Expression.Equal - -- TODO: Distinguish `===` from `==` ? - <|> mk AnonEqualEqualEqual Expression.Equal - <|> mk AnonLAngleEqualRAngle Expression.Comparison - -- TODO: Distinuish `=~` and `!~` ? - <|> mk AnonEqualTilde Expression.Equal - <|> mkNot AnonBangTilde Expression.Equal - <|> mk AnonLAngle Expression.LessThan - <|> mk AnonLAngleEqual Expression.LessThanEqual - <|> mk AnonRAngle Expression.GreaterThan - <|> mk AnonRAngleEqual Expression.GreaterThanEqual - <|> mk AnonAmpersand Expression.BAnd - <|> mk AnonCaret Expression.BXOr - <|> mk AnonPipe Expression.BOr - <|> mk AnonPlus Expression.Plus - <|> mk AnonSlash Expression.DividedBy - <|> mk AnonPercent Expression.Modulo - <|> mk AnonStarStar Expression.Power - <|> mk AnonMinus' Expression.Minus - <|> mk AnonStar' Expression.Times - where mk s constr = makeTerm loc <$> (symbol s *> (constr lexpression <$> expression)) - mkNot s constr = makeTerm loc <$ symbol s <*> (Expression.Not <$> (makeTerm <$> location <*> (constr lexpression <$> expression))) +binary = makeTerm' <$> symbol Binary <*> children (infixTerm expression expression + [ (inj .) . Expression.Plus <$ symbol AnonPlus + , (inj .) . Expression.Minus <$ symbol AnonMinus' + , (inj .) . Expression.Times <$ symbol AnonStar' + , (inj .) . Expression.Power <$ symbol AnonStarStar + , (inj .) . Expression.DividedBy <$ symbol AnonSlash + , (inj .) . Expression.Modulo <$ symbol AnonPercent + , (inj .) . Expression.And <$ (symbol AnonAnd <|> symbol AnonAmpersandAmpersand) + , (inj .) . Expression.BAnd <$ symbol AnonAmpersand + , (inj .) . Expression.Or <$ (symbol AnonOr <|> symbol AnonPipePipe) + , (inj .) . Expression.BOr <$ symbol AnonPipe + , (inj .) . Expression.BXOr <$ symbol AnonCaret + , (inj .) . Expression.Equal <$ (symbol AnonEqualEqual <|> symbol AnonEqualEqualEqual <|> symbol AnonEqualTilde) + , (inj .) . invert Expression.Equal <$ (symbol AnonBangEqual <|> symbol AnonBangTilde) + , (inj .) . Expression.LShift <$ symbol AnonLAngleLAngle + , (inj .) . Expression.RShift <$ symbol AnonRAngleRAngle + , (inj .) . Expression.Comparison <$ symbol AnonLAngleEqualRAngle + , (inj .) . Expression.LessThan <$ symbol AnonLAngle + , (inj .) . Expression.GreaterThan <$ symbol AnonRAngle + , (inj .) . Expression.LessThanEqual <$ symbol AnonLAngleEqual + , (inj .) . Expression.GreaterThanEqual <$ symbol AnonRAngleEqual + ]) + where invert cons a b = Expression.Not (makeTerm1 (cons a b)) conditional :: Assignment conditional = makeTerm <$> symbol Conditional <*> children (Statement.If <$> expression <*> expression <*> expression) @@ -395,3 +412,15 @@ emptyStatement = makeTerm <$> symbol EmptyStatement <*> (Syntax.Empty <$ source invert :: Assignment -> Assignment invert term = makeTerm <$> location <*> fmap Expression.Not term + +-- | Match a term optionally preceded by comment(s), or a sequence of comments if the term is not present. +term :: Assignment -> Assignment +term term = contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm) + +-- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. +infixTerm :: HasCallStack + => Assignment + -> Assignment + -> [Assignment.Assignment (AST Grammar) Grammar (Term -> Term -> Union Syntax Term)] + -> Assignment.Assignment (AST Grammar) Grammar (Union Syntax Term) +infixTerm = infixContext comment From 55e87d30951ab641467383a1ea98769a734f19df Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 13:44:30 -0700 Subject: [PATCH 03/12] Allow comments in assignments --- src/Language/Ruby/Syntax.hs | 43 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index a0828f48e..a35398e9a 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -343,27 +343,30 @@ begin = makeTerm <$> symbol Begin <*> children (Statement.Try <$> expressions <* assignment' :: Assignment assignment' = makeTerm <$> symbol Assignment <*> children (Statement.Assignment <$> lhs <*> rhs) - <|> makeTerm <$> symbol OperatorAssignment <*> children (lhs >>= \ var -> Statement.Assignment var <$> - (makeTerm <$> symbol AnonPlusEqual <*> (Expression.Plus var <$> expression) - <|> makeTerm <$> symbol AnonMinusEqual <*> (Expression.Minus var <$> expression) - <|> makeTerm <$> symbol AnonStarEqual <*> (Expression.Times var <$> expression) - <|> makeTerm <$> symbol AnonStarStarEqual <*> (Expression.Power var <$> expression) - <|> makeTerm <$> symbol AnonSlashEqual <*> (Expression.DividedBy var <$> expression) - <|> makeTerm <$> symbol AnonPipePipeEqual <*> (Expression.And var <$> expression) - <|> makeTerm <$> symbol AnonPipeEqual <*> (Expression.BOr var <$> expression) - <|> makeTerm <$> symbol AnonAmpersandAmpersandEqual <*> (Expression.And var <$> expression) - <|> makeTerm <$> symbol AnonAmpersandEqual <*> (Expression.BAnd var <$> expression) - <|> makeTerm <$> symbol AnonPercentEqual <*> (Expression.Modulo var <$> expression) - <|> makeTerm <$> symbol AnonRAngleRAngleEqual <*> (Expression.RShift var <$> expression) - <|> makeTerm <$> symbol AnonLAngleLAngleEqual <*> (Expression.LShift var <$> expression) - <|> makeTerm <$> symbol AnonCaretEqual <*> (Expression.BXOr var <$> expression))) + <|> makeTerm' <$> symbol OperatorAssignment <*> children (infixTerm lhs expression + [ assign Expression.Plus <$ symbol AnonPlusEqual + , assign Expression.Minus <$ symbol AnonMinusEqual + , assign Expression.Times <$ symbol AnonStarEqual + , assign Expression.Power <$ symbol AnonStarStarEqual + , assign Expression.DividedBy <$ symbol AnonSlashEqual + , assign Expression.And <$ symbol AnonPipePipeEqual + , assign Expression.BOr <$ symbol AnonPipeEqual + , assign Expression.And <$ symbol AnonAmpersandAmpersandEqual + , assign Expression.BAnd <$ symbol AnonAmpersandEqual + , assign Expression.Modulo <$ symbol AnonPercentEqual + , assign Expression.RShift <$ symbol AnonRAngleRAngleEqual + , assign Expression.LShift <$ symbol AnonLAngleLAngleEqual + , assign Expression.BXOr <$ symbol AnonCaretEqual + ]) where - lhs = makeTerm <$> symbol LeftAssignmentList <*> children (many expr) <|> expr - rhs = makeTerm <$> symbol RightAssignmentList <*> children (many expr) <|> expr - expr = - makeTerm <$> symbol RestAssignment <*> (Syntax.Identifier <$> source) - <|> makeTerm <$> symbol DestructuredLeftAssignment <*> children (many expr) - <|> expression + assign :: f :< Syntax => (Term -> Term -> f Term) -> Term -> Term -> Union Syntax Term + assign c l r = inj (Statement.Assignment l (makeTerm1 (c l r))) + + lhs = makeTerm <$> symbol LeftAssignmentList <*> children (many expr) <|> expr + rhs = makeTerm <$> symbol RightAssignmentList <*> children (many expr) <|> expr + expr = makeTerm <$> symbol RestAssignment <*> (Syntax.Identifier <$> source) + <|> makeTerm <$> symbol DestructuredLeftAssignment <*> children (many expr) + <|> expression unary :: Assignment unary = symbol Unary >>= \ location -> From 4fa472f8a1031cab0bff912329b9965b3cfd89a8 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:11:09 -0700 Subject: [PATCH 04/12] Comments in hashes, simplify a few literals --- src/Language/Ruby/Syntax.hs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index a35398e9a..98c5d9309 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -176,17 +176,17 @@ identifier = literal :: Assignment literal = - makeTerm <$> symbol Grammar.True <*> (Literal.true <$ source) - <|> makeTerm <$> symbol Grammar.False <*> (Literal.false <$ source) + makeTerm <$> token Grammar.True <*> pure Literal.true + <|> makeTerm <$> token Grammar.False <*> pure Literal.false + <|> makeTerm <$> token Grammar.Nil <*> pure Literal.Null <|> makeTerm <$> symbol Grammar.Integer <*> (Literal.Integer <$> source) <|> makeTerm <$> symbol Grammar.Float <*> (Literal.Float <$> source) - <|> makeTerm <$> symbol Grammar.Nil <*> (Literal.Null <$ source) <|> makeTerm <$> symbol Grammar.Rational <*> (Language.Ruby.Syntax.Rational <$> source) <|> makeTerm <$> symbol Grammar.Complex <*> (Language.Ruby.Syntax.Complex <$> source) -- TODO: Do we want to represent the difference between .. and ... <|> makeTerm <$> symbol Range <*> children (Expression.Enumeration <$> expression <*> expression <*> emptyTerm) <|> makeTerm <$> symbol Array <*> children (Literal.Array <$> many expression) - <|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> many pair) + <|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> (many . term) pair) -- TODO: Give subshell it's own literal and allow interpolation <|> makeTerm <$> symbol Subshell <*> (Literal.TextElement <$> source) -- TODO: Handle interpolation @@ -320,7 +320,6 @@ methodCall = makeTerm <$> symbol MethodCall <*> children (Expression.Call <$> ex where args = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (many expression) <|> pure [] - call :: Assignment call = makeTerm <$> symbol Call <*> children (Expression.MemberAccess <$> expression <*> (expression <|> args)) where From 680ad37eeaa07c6316459dfca91d9d5a4fa6b426 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:14:33 -0700 Subject: [PATCH 05/12] Fix up chained strings, allow comments --- src/Language/Ruby/Syntax.hs | 8 ++------ test/fixtures/ruby/hash.A.rb | 11 +++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index 98c5d9309..d2ac6db29 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -174,6 +174,7 @@ identifier = <|> mk Uninterpreted where mk s = makeTerm <$> symbol s <*> (Syntax.Identifier <$> source) +-- TODO: Handle interpolation in all literals that support it (strings, regexes, symbols, subshells, etc). literal :: Assignment literal = makeTerm <$> token Grammar.True <*> pure Literal.true @@ -187,15 +188,10 @@ literal = <|> makeTerm <$> symbol Range <*> children (Expression.Enumeration <$> expression <*> expression <*> emptyTerm) <|> makeTerm <$> symbol Array <*> children (Literal.Array <$> many expression) <|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> (many . term) pair) - -- TODO: Give subshell it's own literal and allow interpolation <|> makeTerm <$> symbol Subshell <*> (Literal.TextElement <$> source) - -- TODO: Handle interpolation <|> makeTerm <$> symbol String <*> (Literal.TextElement <$> source) - -- TODO: this isn't quite right `"a" "b"` ends up as TextElement {textElementContent = "\"a\"\"b\""} - <|> makeTerm <$> symbol ChainedString <*> children (Literal.TextElement . mconcat <$> many (symbol String *> source)) - -- TODO: Handle interpolation, dedicated literal? + <|> makeTerm <$> symbol ChainedString <*> children (many (term (makeTerm <$> symbol String <*> (Literal.TextElement <$> source)))) <|> makeTerm <$> symbol Regex <*> (Literal.TextElement <$> source) - -- TODO: Handle interpolation <|> makeTerm <$> symbol Symbol <*> (Literal.Symbol <$> source) heredoc :: Assignment diff --git a/test/fixtures/ruby/hash.A.rb b/test/fixtures/ruby/hash.A.rb index 925618f35..49646f087 100644 --- a/test/fixtures/ruby/hash.A.rb +++ b/test/fixtures/ruby/hash.A.rb @@ -1 +1,12 @@ { :key1 => "value", :key2 => 1, "key3" => false, :"symbol_key" => 10 } +{} +{ + #comment + a: 1, # comment + #comment + 'a' => 1 + #comment +} +{ + #foo +} From 41b843ed7095fa90b976119a755771880a76eadc Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:28:00 -0700 Subject: [PATCH 06/12] Formatting --- src/Language/Ruby/Syntax.hs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index d2ac6db29..97c5c03ef 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -336,23 +336,22 @@ begin :: Assignment begin = makeTerm <$> symbol Begin <*> children (Statement.Try <$> expressions <*> many rescue) assignment' :: Assignment -assignment' - = makeTerm <$> symbol Assignment <*> children (Statement.Assignment <$> lhs <*> rhs) - <|> makeTerm' <$> symbol OperatorAssignment <*> children (infixTerm lhs expression - [ assign Expression.Plus <$ symbol AnonPlusEqual - , assign Expression.Minus <$ symbol AnonMinusEqual - , assign Expression.Times <$ symbol AnonStarEqual - , assign Expression.Power <$ symbol AnonStarStarEqual - , assign Expression.DividedBy <$ symbol AnonSlashEqual - , assign Expression.And <$ symbol AnonPipePipeEqual - , assign Expression.BOr <$ symbol AnonPipeEqual - , assign Expression.And <$ symbol AnonAmpersandAmpersandEqual - , assign Expression.BAnd <$ symbol AnonAmpersandEqual - , assign Expression.Modulo <$ symbol AnonPercentEqual - , assign Expression.RShift <$ symbol AnonRAngleRAngleEqual - , assign Expression.LShift <$ symbol AnonLAngleLAngleEqual - , assign Expression.BXOr <$ symbol AnonCaretEqual - ]) +assignment' = makeTerm <$> symbol Assignment <*> children (Statement.Assignment <$> lhs <*> rhs) + <|> makeTerm' <$> symbol OperatorAssignment <*> children (infixTerm lhs expression + [ assign Expression.Plus <$ symbol AnonPlusEqual + , assign Expression.Minus <$ symbol AnonMinusEqual + , assign Expression.Times <$ symbol AnonStarEqual + , assign Expression.Power <$ symbol AnonStarStarEqual + , assign Expression.DividedBy <$ symbol AnonSlashEqual + , assign Expression.And <$ symbol AnonPipePipeEqual + , assign Expression.BOr <$ symbol AnonPipeEqual + , assign Expression.And <$ symbol AnonAmpersandAmpersandEqual + , assign Expression.BAnd <$ symbol AnonAmpersandEqual + , assign Expression.Modulo <$ symbol AnonPercentEqual + , assign Expression.RShift <$ symbol AnonRAngleRAngleEqual + , assign Expression.LShift <$ symbol AnonLAngleLAngleEqual + , assign Expression.BXOr <$ symbol AnonCaretEqual + ]) where assign :: f :< Syntax => (Term -> Term -> f Term) -> Term -> Term -> Union Syntax Term assign c l r = inj (Statement.Assignment l (makeTerm1 (c l r))) From 52d956894b211749f6a08fce215f4f9d3132881c Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:28:10 -0700 Subject: [PATCH 07/12] Update hash fixtures --- test/fixtures/ruby/hash.diffA-B.txt | 16 +++++++++++++++- test/fixtures/ruby/hash.diffB-A.txt | 16 +++++++++++++++- test/fixtures/ruby/hash.parseA.txt | 16 +++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/test/fixtures/ruby/hash.diffA-B.txt b/test/fixtures/ruby/hash.diffA-B.txt index 9b25d2e89..c55df5ce1 100644 --- a/test/fixtures/ruby/hash.diffA-B.txt +++ b/test/fixtures/ruby/hash.diffA-B.txt @@ -17,4 +17,18 @@ ->(Boolean) }) {-(Pair (SymbolLiteral) - (IntegerLiteral))-})) + (IntegerLiteral))-}) +{-(Object)-} +{-(Object + (Comment) + (Pair + (Identifier) + (IntegerLiteral)) + (Comment) + (Comment) + (Pair + (StringLiteral) + (IntegerLiteral)) + (Comment))-} +{-(Object + (Comment))-}) diff --git a/test/fixtures/ruby/hash.diffB-A.txt b/test/fixtures/ruby/hash.diffB-A.txt index fefff314a..51150fa26 100644 --- a/test/fixtures/ruby/hash.diffB-A.txt +++ b/test/fixtures/ruby/hash.diffB-A.txt @@ -17,4 +17,18 @@ ->(Boolean) }) {+(Pair (SymbolLiteral) - (IntegerLiteral))+})) + (IntegerLiteral))+}) +{+(Object)+} +{+(Object + (Comment) + (Pair + (Identifier) + (IntegerLiteral)) + (Comment) + (Comment) + (Pair + (StringLiteral) + (IntegerLiteral)) + (Comment))+} +{+(Object + (Comment))+}) diff --git a/test/fixtures/ruby/hash.parseA.txt b/test/fixtures/ruby/hash.parseA.txt index 9880b8c10..73d807f0c 100644 --- a/test/fixtures/ruby/hash.parseA.txt +++ b/test/fixtures/ruby/hash.parseA.txt @@ -11,4 +11,18 @@ (Boolean)) (Pair (SymbolLiteral) - (IntegerLiteral)))) + (IntegerLiteral))) + (Object) + (Object + (Comment) + (Pair + (Identifier) + (IntegerLiteral)) + (Comment) + (Comment) + (Pair + (StringLiteral) + (IntegerLiteral)) + (Comment)) + (Object + (Comment))) From ada7f4d4dbc08b9e14acc458e74100a66de5922d Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:33:50 -0700 Subject: [PATCH 08/12] Not using this import --- src/Language/Ruby/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index 97c5c03ef..679e74cf9 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -15,7 +15,7 @@ import Data.Functor (void) import Data.Functor.Classes.Eq.Generic import Data.Functor.Classes.Show.Generic import Data.List.NonEmpty (some1) -import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm1, postContextualize) +import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm1) import qualified Data.Syntax as Syntax import Data.Syntax.Assignment hiding (Assignment, Error) import qualified Data.Syntax.Assignment as Assignment From d9da2c1339d5bf49301f6475a22282a3a4655d92 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:34:44 -0700 Subject: [PATCH 09/12] Docs --- src/Language/Ruby/Syntax.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index 679e74cf9..c683049e4 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -86,13 +86,14 @@ type Syntax = '[ type Term = Term.Term (Union Syntax) (Record Location) type Assignment = HasCallStack => Assignment.Assignment (AST Grammar) Grammar Term --- Rational literal e.g. `2/3r` +-- Rational literals e.g. `2/3r` newtype Rational a = Rational ByteString deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 Language.Ruby.Syntax.Rational where liftEq = genericLiftEq instance Show1 Language.Ruby.Syntax.Rational where liftShowsPrec = genericLiftShowsPrec +-- Complex literals e.g. `3 + 2i` newtype Complex a = Complex ByteString deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) From bb86b5241df4d4b75219f892dc32057949b4ba05 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:45:06 -0700 Subject: [PATCH 10/12] Use token for pair with no children --- src/Language/Ruby/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index c683049e4..b79a2e8f2 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -310,7 +310,7 @@ subscript = makeTerm <$> symbol ElementReference <*> children (Expression.Subscr pair :: Assignment pair = makeTerm <$> symbol Pair <*> children (Literal.KeyValue <$> expression <*> expression) - <|> makeTerm <$> symbol Pair <*> (Syntax.Empty <$ source) + <|> makeTerm <$> token Pair <*> pure Syntax.Empty methodCall :: Assignment methodCall = makeTerm <$> symbol MethodCall <*> children (Expression.Call <$> expression <*> args <*> (block <|> emptyTerm)) From c7fd754af8287380a5d47f71da088b489f1ad3e6 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Wed, 16 Aug 2017 14:45:18 -0700 Subject: [PATCH 11/12] Line em up --- src/Language/Ruby/Syntax.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index b79a2e8f2..3caee976a 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -417,8 +417,8 @@ term term = contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> som -- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. infixTerm :: HasCallStack - => Assignment - -> Assignment - -> [Assignment.Assignment (AST Grammar) Grammar (Term -> Term -> Union Syntax Term)] - -> Assignment.Assignment (AST Grammar) Grammar (Union Syntax Term) + => Assignment + -> Assignment + -> [Assignment.Assignment (AST Grammar) Grammar (Term -> Term -> Union Syntax Term)] + -> Assignment.Assignment (AST Grammar) Grammar (Union Syntax Term) infixTerm = infixContext comment From 77409b0045f75e3fa0dd43e7c4254accb79f1735 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Mon, 21 Aug 2017 08:44:33 -0700 Subject: [PATCH 12/12] Move rational and complex in Data.Syntax.Literal --- src/Data/Syntax/Literal.hs | 14 ++++++++++++++ src/Language/Ruby/Syntax.hs | 29 ++++------------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/Data/Syntax/Literal.hs b/src/Data/Syntax/Literal.hs index 4e4baf989..40346d8c0 100644 --- a/src/Data/Syntax/Literal.hs +++ b/src/Data/Syntax/Literal.hs @@ -44,6 +44,20 @@ newtype Float a = Float { floatContent :: ByteString } instance Eq1 Data.Syntax.Literal.Float where liftEq = genericLiftEq instance Show1 Data.Syntax.Literal.Float where liftShowsPrec = genericLiftShowsPrec +-- Rational literals e.g. `2/3r` +newtype Rational a = Rational ByteString + deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Data.Syntax.Literal.Rational where liftEq = genericLiftEq +instance Show1 Data.Syntax.Literal.Rational where liftShowsPrec = genericLiftShowsPrec + +-- Complex literals e.g. `3 + 2i` +newtype Complex a = Complex ByteString + deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Data.Syntax.Literal.Complex where liftEq = genericLiftEq +instance Show1 Data.Syntax.Literal.Complex where liftShowsPrec = genericLiftShowsPrec + -- Strings, symbols newtype String a = String { stringElements :: [a] } diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index 3caee976a..6b414b5d4 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -6,14 +6,9 @@ module Language.Ruby.Syntax , Term ) where -import Algorithm -import Data.Align.Generic -import Data.ByteString import Data.Maybe (fromMaybe) import Data.Record import Data.Functor (void) -import Data.Functor.Classes.Eq.Generic -import Data.Functor.Classes.Show.Generic import Data.List.NonEmpty (some1) import Data.Syntax (contextualize, emptyTerm, parseError, handleError, infixContext, makeTerm, makeTerm', makeTerm1) import qualified Data.Syntax as Syntax @@ -25,7 +20,6 @@ import qualified Data.Syntax.Expression as Expression import qualified Data.Syntax.Literal as Literal import qualified Data.Syntax.Statement as Statement import Data.Union -import GHC.Generics import GHC.Stack import Language.Ruby.Grammar as Grammar import qualified Term @@ -46,15 +40,15 @@ type Syntax = '[ , Expression.MemberAccess , Expression.ScopeResolution , Expression.Subscript - , Language.Ruby.Syntax.Rational - , Language.Ruby.Syntax.Complex , Literal.Array , Literal.Boolean + , Literal.Complex , Literal.Float , Literal.Hash , Literal.Integer , Literal.KeyValue , Literal.Null + , Literal.Rational , Literal.String , Literal.Symbol , Literal.TextElement @@ -86,21 +80,6 @@ type Syntax = '[ type Term = Term.Term (Union Syntax) (Record Location) type Assignment = HasCallStack => Assignment.Assignment (AST Grammar) Grammar Term --- Rational literals e.g. `2/3r` -newtype Rational a = Rational ByteString - deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) - -instance Eq1 Language.Ruby.Syntax.Rational where liftEq = genericLiftEq -instance Show1 Language.Ruby.Syntax.Rational where liftShowsPrec = genericLiftShowsPrec - --- Complex literals e.g. `3 + 2i` -newtype Complex a = Complex ByteString - deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) - -instance Eq1 Language.Ruby.Syntax.Complex where liftEq = genericLiftEq -instance Show1 Language.Ruby.Syntax.Complex where liftShowsPrec = genericLiftShowsPrec - - -- | Assignment from AST in Ruby’s grammar onto a program in Ruby’s syntax. assignment :: Assignment assignment = handleError $ makeTerm <$> symbol Program <*> children (Syntax.Program <$> many expression) @@ -183,8 +162,8 @@ literal = <|> makeTerm <$> token Grammar.Nil <*> pure Literal.Null <|> makeTerm <$> symbol Grammar.Integer <*> (Literal.Integer <$> source) <|> makeTerm <$> symbol Grammar.Float <*> (Literal.Float <$> source) - <|> makeTerm <$> symbol Grammar.Rational <*> (Language.Ruby.Syntax.Rational <$> source) - <|> makeTerm <$> symbol Grammar.Complex <*> (Language.Ruby.Syntax.Complex <$> source) + <|> makeTerm <$> symbol Grammar.Rational <*> (Literal.Rational <$> source) + <|> makeTerm <$> symbol Grammar.Complex <*> (Literal.Complex <$> source) -- TODO: Do we want to represent the difference between .. and ... <|> makeTerm <$> symbol Range <*> children (Expression.Enumeration <$> expression <*> expression <*> emptyTerm) <|> makeTerm <$> symbol Array <*> children (Literal.Array <$> many expression)