1
1
mirror of https://github.com/github/semantic.git synced 2025-01-05 14:11:33 +03:00

Merge branch 'master' into assignment-optimization

This commit is contained in:
Rob Rix 2017-08-16 14:40:36 -04:00
commit 7074a18012
25 changed files with 292 additions and 179 deletions

View File

@ -3,7 +3,8 @@ module Algorithm where
import Control.Applicative (liftA2)
import Control.Monad (guard, join)
import Control.Monad.Free.Freer
import Control.Monad.Free (wrap)
import Control.Monad.Free.Freer hiding (wrap)
import Data.Function (on)
import Data.Functor.Both
import Data.Functor.Classes

View File

@ -25,30 +25,38 @@ import Term
-- Combinators
-- | Lift syntax and an annotation into a term, injecting the syntax into a union & ensuring the annotation encompasses all children.
makeTerm :: (HasCallStack, f :< fs, Semigroup a, Apply1 Foldable fs) => a -> f (Term (Union fs) a) -> Term (Union fs) a
makeTerm a = makeTerm' a . inj
-- | Lift a union and an annotation into a term, ensuring the annotation encompasses all children.
makeTerm' :: (HasCallStack, Semigroup a, Foldable f) => a -> f (Term f a) -> Term f a
makeTerm' a f = cofree (sconcat (a :| (headF . runCofree <$> toList f)) :< f)
-- | Lift non-empty syntax into a term, injecting the syntax into a union & appending all subterms.annotations to make the new terms annotation.
makeTerm1 :: (HasCallStack, f :< fs, Semigroup a, Apply1 Foldable fs) => f (Term (Union fs) a) -> Term (Union fs) a
makeTerm1 = makeTerm1' . inj
-- | Lift a non-empty union into a term, appending all subterms.annotations to make the new terms annotation.
makeTerm1' :: (HasCallStack, Semigroup a, Foldable f) => f (Term f a) -> Term f a
makeTerm1' f = case toList f of
a : _ -> makeTerm' (headF (runCofree a)) f
_ -> error "makeTerm1': empty structure"
-- | Construct an empty term at the current position.
emptyTerm :: (HasCallStack, Empty :< fs, Apply1 Foldable fs) => Assignment.Assignment ast grammar (Term (Union fs) (Record Assignment.Location))
emptyTerm = makeTerm <$> Assignment.location <*> pure Empty
-- | Catch assignment errors into an error term.
handleError :: (HasCallStack, Error :< fs, Show grammar, Apply1 Foldable fs) => Assignment.Assignment ast grammar (Term (Union fs) (Record Assignment.Location)) -> Assignment.Assignment ast grammar (Term (Union fs) (Record Assignment.Location))
handleError = flip catchError (\ err -> makeTerm <$> Assignment.location <*> pure (errorSyntax (either id show <$> err) []) <* Assignment.source)
-- | Catch parse errors into an error term.
parseError :: (HasCallStack, Error :< fs, Bounded grammar, Ix grammar, Apply1 Foldable fs) => Assignment.Assignment ast grammar (Term (Union fs) (Record Assignment.Location))
parseError = makeTerm <$> Assignment.symbol maxBound <*> pure (Error (getCallStack (freezeCallStack callStack)) [] Nothing []) <* Assignment.source
-- | Match context terms before a subject term, wrapping both up in a Context term if any context terms matched, or otherwise returning the subject term.
contextualize :: (HasCallStack, Context :< fs, Alternative m, Semigroup a, Apply1 Foldable fs)
=> m (Term (Union fs) a)
-> m (Term (Union fs) a)
@ -58,6 +66,7 @@ contextualize context rule = make <$> Assignment.manyThrough context rule
Just cs -> makeTerm1 (Context cs node)
_ -> node
-- | Match context terms after a subject term and before a delimiter, returning the delimiter paired with a Context term if any context terms matched, or the subject term otherwise.
postContextualizeThrough :: (HasCallStack, Context :< fs, Alternative m, Semigroup a, Apply1 Foldable fs)
=> m (Term (Union fs) a)
-> m (Term (Union fs) a)
@ -68,6 +77,7 @@ postContextualizeThrough context rule end = make <$> rule <*> Assignment.manyThr
Just cs -> (makeTerm1 (Context cs node), end)
_ -> (node, end)
-- | Match context terms after a subject term, wrapping both up in a Context term if any context terms matched, or otherwise returning the subject term.
postContextualize :: (HasCallStack, Context :< fs, Alternative m, Semigroup a, Apply1 Foldable fs)
=> m (Term (Union fs) a)
-> m (Term (Union fs) a)
@ -77,6 +87,7 @@ postContextualize context rule = make <$> rule <*> many context
Just cs -> makeTerm1 (Context cs node)
_ -> node
-- | Match infix terms separated by any of a list of operators, with optional context terms following each operand.
infixContext :: (Context :< fs, Assignment.Parsing m, Semigroup a, HasCallStack, Apply1 Foldable fs)
=> m (Term (Union fs) a)
-> m (Term (Union fs) a)

View File

@ -76,7 +76,6 @@ module Data.Syntax.Assignment
, children
, advance
, token
, infixChoice
, while
, until
, manyThrough
@ -163,15 +162,14 @@ source = withFrozenCallStack $ Source `Then` return
children :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar a
children forEach = withFrozenCallStack $ Children forEach `Then` return
-- | Advance past the current node.
advance :: HasCallStack => Assignment ast grammar ()
advance = withFrozenCallStack $ Advance `Then` return
-- | Match and advance past a node with the given symbol.
token :: (Bounded grammar, Ix grammar, HasCallStack) => grammar -> Assignment ast grammar (Record Location)
token s = symbol s <* advance
infixChoice :: (Alternative m, HasCallStack) => m a -> m b -> [m (a -> b -> c)] -> m c
infixChoice left right operators = (&) <$> left <*> choice operators <*> right
-- | Collect a list of values passing a predicate.
while :: (Alternative m, Monad m, HasCallStack) => (a -> Bool) -> m a -> m [a]
@ -184,6 +182,7 @@ while predicate step = many $ do
until :: (Alternative m, Monad m, HasCallStack) => (a -> Bool) -> m a -> m [a]
until = while . (not .)
-- | Match the first operand until the second operand matches, returning both results. Like 'manyTill', but returning the terminal value.
manyThrough :: (Alternative m, HasCallStack) => m a -> m b -> m ([a], b)
manyThrough step stop = go
where go = (,) [] <$> stop <|> first . (:) <$> step <*> go

View File

@ -9,8 +9,8 @@ module Interpreter
import Algorithm
import Control.Comonad (extract)
import Control.Comonad.Cofree (unwrap)
import Control.Monad.Free (cutoff)
import Control.Monad.Free.Freer hiding (cutoff)
import Control.Monad.Free (cutoff, wrap)
import Control.Monad.Free.Freer hiding (cutoff, wrap)
import Data.Align.Generic
import Data.Functor.Both
import Data.Functor.Classes (Eq1)

View File

@ -470,15 +470,19 @@ ifClause = symbol IfClause *> children expressions
conditionalExpression :: Assignment
conditionalExpression = makeTerm <$> symbol ConditionalExpression <*> children (flip Statement.If <$> expression <*> expression <*> expressions)
-- | 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 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
-- | Match a series of terms or comments until a delimiter is matched.
manyTermsTill :: Show b => Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar [Term]
manyTermsTill step end = manyTill (step <|> comment) end
-- | Match infix terms separated by any of a list of operators, assigning any comments following each operand.
infixTerm :: HasCallStack
=> Assignment
-> Assignment

View File

@ -5,6 +5,8 @@ import Language.Haskell.TH
import TreeSitter.Language
import TreeSitter.Ruby
-- v2 - Bump to get file to change to force template haskell to regenerate.
-- Regenerate template haskell code when these files change:
addDependentFileRelative "../../../vendor/haskell-tree-sitter/languages/ruby/vendor/tree-sitter-ruby/src/parser.c"
-- | Statically-known rules corresponding to symbols in the grammar.
mkSymbolDatatype (mkName "Grammar") tree_sitter_ruby

View File

@ -8,7 +8,8 @@ module Language.Ruby.Syntax
import Data.Maybe (fromMaybe)
import Data.Record
import Data.Syntax (emptyTerm, makeTerm, parseError)
import Data.Functor (void)
import Data.Syntax (emptyTerm, makeTerm, parseError, handleError)
import qualified Data.Syntax as Syntax
import Data.Syntax.Assignment hiding (Assignment, Error)
import qualified Data.Syntax.Assignment as Assignment
@ -78,58 +79,64 @@ type Assignment = HasCallStack => Assignment.Assignment [] Grammar Term
-- | Assignment from AST in Rubys grammar onto a program in Rubys syntax.
assignment :: Assignment
assignment = makeTerm <$> symbol Program <*> children (Syntax.Program <$> many expression) <|> parseError
assignment = handleError $ makeTerm <$> symbol Program <*> children (Syntax.Program <$> many expression)
expression :: Assignment
expression =
beginBlock
<|> endBlock
<|> comment
<|> undef
<|> alias
<|> if'
<|> unless
<|> while'
<|> until'
<|> case'
<|> emptyStatement
expression = handleError $
alias
<|> assignment'
<|> unary
<|> begin
<|> beginBlock
<|> binary
<|> literal
<|> block
<|> call
<|> case'
<|> class'
<|> comment
<|> conditional
<|> emptyStatement
<|> endBlock
<|> for
<|> heredoc
<|> identifier
<|> if'
<|> keyword
<|> mk Return Statement.Return
<|> mk Yield Statement.Yield
<|> lambda
<|> literal
<|> method
<|> methodCall
<|> mk Break Statement.Break
<|> mk Next Statement.Continue
<|> mk Redo Statement.Retry
<|> mk Retry Statement.Retry
<|> for
<|> class'
<|> singletonClass
<|> method
<|> singletonMethod
<|> lambda
<|> mk Return Statement.Return
<|> mk Yield Statement.Yield
<|> module'
<|> identifier
<|> scopeResolution
<|> conditional
<|> methodCall
<|> call
<|> subscript
<|> begin
<|> pair
<|> parenthesized_expressions
<|> rescue
<|> block
<|> heredoc
<|> scopeResolution
<|> singletonClass
<|> singletonMethod
<|> subscript
<|> unary
<|> undef
<|> unless
<|> until'
<|> while'
<|> parseError
where mk s construct = makeTerm <$> symbol s <*> children ((construct .) . fromMaybe <$> emptyTerm <*> optional (symbol ArgumentList *> children expression))
where mk s construct = makeTerm <$> symbol s <*> children ((construct .) . fromMaybe <$> emptyTerm <*> optional (symbol ArgumentList *> children expressions))
expressions :: Assignment
expressions = makeTerm <$> location <*> many expression
parenthesized_expressions :: Assignment
parenthesized_expressions = makeTerm <$> symbol ParenthesizedStatements <*> children (many expression)
identifier :: Assignment
identifier =
mk Identifier
<|> mk Identifier'
<|> mk Constant
<|> mk InstanceVariable
<|> mk ClassVariable
@ -138,6 +145,9 @@ identifier =
<|> mk Self
<|> mk Super
<|> mk Setter
<|> mk SplatArgument
<|> mk HashSplatArgument
<|> mk BlockArgument
<|> mk ReservedIdentifier
<|> mk Uninterpreted
where mk s = makeTerm <$> symbol s <*> (Syntax.Identifier <$> source)
@ -238,18 +248,20 @@ undef = makeTerm <$> symbol Undef <*> children (Expression.Call <$> name <*> som
where name = makeTerm <$> location <*> (Syntax.Identifier <$> source)
if' :: Assignment
if' =
ifElsif If
<|> makeTerm <$> symbol IfModifier <*> children (flip Statement.If <$> expression <*> expression <*> emptyTerm)
where ifElsif s = makeTerm <$> symbol s <*> children (Statement.If <$> expression <*> expressions <*> (fromMaybe <$> emptyTerm <*> optional (ifElsif Elsif <|> else')))
if' = ifElsif If
<|> makeTerm <$> symbol IfModifier <*> children (flip Statement.If <$> expression <*> expression <*> emptyTerm)
where
ifElsif s = makeTerm <$> symbol s <*> children (Statement.If <$> expression <*> expressions' <*> (fromMaybe <$> emptyTerm <*> optional (ifElsif Elsif <|> else')))
expressions' = makeTerm <$> location <*> manyTill expression (void (symbol Else) <|> void (symbol Elsif) <|> eof)
else' :: Assignment
else' = makeTerm <$> symbol Else <*> children (many expression)
unless :: Assignment
unless =
makeTerm <$> symbol Unless <*> children (Statement.If <$> invert expression <*> expressions <*> (fromMaybe <$> emptyTerm <*> optional else'))
makeTerm <$> symbol Unless <*> children (Statement.If <$> invert expression <*> expressions' <*> (fromMaybe <$> emptyTerm <*> optional else'))
<|> makeTerm <$> symbol UnlessModifier <*> children (flip Statement.If <$> expression <*> invert expression <*> emptyTerm)
where expressions' = makeTerm <$> location <*> manyTill expression (void (symbol Else) <|> eof)
while' :: Assignment
while' =
@ -262,37 +274,33 @@ until' =
<|> makeTerm <$> symbol UntilModifier <*> children (flip Statement.While <$> expression <*> invert expression)
for :: Assignment
for = makeTerm <$> symbol For <*> children (Statement.ForEach <$> vars <*> expression <*> expressions)
where vars = makeTerm <$> location <*> some expression
for = makeTerm <$> symbol For <*> children (Statement.ForEach <$> (makeTerm <$> location <*> manyTill expression (symbol In)) <*> inClause <*> expressions)
where inClause = symbol In *> children (expression)
case' :: Assignment
case' = makeTerm <$> symbol Case <*> children (Statement.Match <$> expression <*> when')
case' = makeTerm <$> symbol Case <*> children (Statement.Match <$> (symbol When *> emptyTerm <|> expression) <*> whens)
where
when' = makeTerm <$> symbol When <*> children (Statement.Pattern <$> (makeTerm <$> location <*> some pattern) <*> (when' <|> else' <|> expressions))
whens = makeTerm <$> location <*> many (when' <|> else' <|> expression)
when' = makeTerm <$> symbol When <*> children (Statement.Pattern <$> (makeTerm <$> location <*> some pattern) <*> whens)
pattern = symbol Pattern *> children ((symbol SplatArgument *> children expression) <|> expression)
subscript :: Assignment
subscript = makeTerm <$> symbol ElementReference <*> children (Expression.Subscript <$> expression <*> many argument)
subscript = makeTerm <$> symbol ElementReference <*> children (Expression.Subscript <$> expression <*> many expression)
pair :: Assignment
pair = makeTerm <$> symbol Pair <*> children (Literal.KeyValue <$> expression <*> expression)
argument :: Assignment
argument =
mk SplatArgument
<|> mk HashSplatArgument
<|> mk BlockArgument
<|> pair
<|> expression
where mk s = makeTerm <$> symbol s <*> (Syntax.Identifier <$> source)
<|> makeTerm <$> symbol Pair <*> (Syntax.Empty <$ source)
methodCall :: Assignment
methodCall = makeTerm <$> symbol MethodCall <*> children (Expression.Call <$> expression <*> args <*> (block <|> emptyTerm))
where
args = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (many argument) <|> pure []
args = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (many expression) <|> pure []
call :: Assignment
call = makeTerm <$> symbol Call <*> children (Expression.MemberAccess <$> expression <*> expression)
call = makeTerm <$> symbol Call <*> children (Expression.MemberAccess <$> expression <*> (expression <|> args))
where
args = (symbol ArgumentList <|> symbol ArgumentListWithParens) *> children (expressions)
rescue :: Assignment
rescue = rescue'
@ -331,7 +339,7 @@ assignment'
expr =
makeTerm <$> symbol RestAssignment <*> (Syntax.Identifier <$> source)
<|> makeTerm <$> symbol DestructuredLeftAssignment <*> children (many expr)
<|> argument
<|> expression
unary :: Assignment
unary = symbol Unary >>= \ location ->
@ -339,11 +347,11 @@ unary = symbol Unary >>= \ location ->
<|> makeTerm location . Expression.Not <$> children ( symbol AnonBang *> expression )
<|> makeTerm location . Expression.Not <$> children ( symbol AnonNot *> expression )
<|> makeTerm location <$> children (Expression.Call <$> (makeTerm <$> symbol AnonDefinedQuestion <*> (Syntax.Identifier <$> source)) <*> some expression <*> emptyTerm)
<|> makeTerm location . Expression.Negate <$> children ( symbol AnonMinus' *> expression )
<|> children ( symbol AnonPlus *> expression )
<|> makeTerm location . Expression.Negate <$> children expression -- Unary minus (e.g. `-a`). HiddenUnaryMinus nodes are hidden, so we can't match on the symbol.
binary :: Assignment
binary = symbol Binary >>= \ loc -> children $ expression >>= \ lexpression -> go loc lexpression
binary = symbol Binary >>= \ loc -> children $ (expression <|> emptyTerm) >>= \ lexpression -> go loc lexpression
where
go loc lexpression
= mk AnonAnd Expression.And
@ -367,13 +375,15 @@ binary = symbol Binary >>= \ loc -> children $ expression >>= \ lexpression -> g
<|> mk AnonAmpersand Expression.BAnd
<|> mk AnonCaret Expression.BXOr
<|> mk AnonPipe Expression.BOr
-- TODO: binary minus (hidden node). Doesn't work b/c we can't match hidden nodes (they aren't in the tree).
-- <|> mk HiddenBinaryMinus Expression.Minus
<|> mk AnonPlus Expression.Plus
-- TODO: binary star (hidden node)
<|> 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))
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)))

View File

@ -5,3 +5,7 @@ end
for x, y in z do
f
end
for n in 1..3 do true end
for n, m in 1..3 do true end

View File

@ -1,12 +0,0 @@
{+(Program
(For
(Identifier)
(Other "in"
(Identifier))
(Identifier))
(For
(Identifier)
(Identifier)
(Other "in"
(Identifier))
(Identifier)))+}

View File

@ -1,12 +0,0 @@
{-(Program
(For
(Identifier)
(Other "in"
(Identifier))
(Identifier))
(For
(Identifier)
(Identifier)
(Other "in"
(Identifier))
(Identifier)))-}

View File

@ -1,20 +1,39 @@
(Program
(For
{ (Identifier)
->(Identifier) }
{+(For
(Identifier)
(Other "in"
{+(ArrayLiteral
(ArrayLiteral
(IntegerLiteral)
(IntegerLiteral)
(IntegerLiteral))+}
{-(Identifier)-})
{ (Identifier)
->(MethodCall
(IntegerLiteral)))
(MethodCall
(Identifier)
(Identifier)) })
(Identifier)))+}
{-(For
(Identifier)
(Other "in"
(Identifier))
(Identifier))-}
{-(For
(Identifier)
(Identifier)
(Other "in"
(Identifier))
(Identifier))-})
(Identifier))-}
{-(For
(Identifier)
(Other "in"
(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral)))
(Boolean))-}
{-(For
(Identifier)
(Identifier)
(Other "in"
(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral)))
(Boolean))-})

View File

@ -1,9 +1,23 @@
(Program
{+(For
(Identifier)
(Other "in"
(Identifier))
(Identifier))+}
{+(For
(Identifier)
(Identifier)
(Other "in"
(Identifier))
(Identifier))+}
(For
{ (Identifier)
->(Identifier) }
(Other "in"
{+(Identifier)+}
{+(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral))+}
{-(ArrayLiteral
(IntegerLiteral)
(IntegerLiteral)
@ -11,10 +25,13 @@
{ (MethodCall
(Identifier)
(Identifier))
->(Identifier) })
->(Boolean) })
{+(For
(Identifier)
(Identifier)
(Other "in"
(Identifier))
(Identifier))+})
(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral)))
(Boolean))+})

View File

@ -9,4 +9,21 @@
(Identifier)
(Other "in"
(Identifier))
(Identifier)))
(Identifier))
(For
(Identifier)
(Other "in"
(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral)))
(Boolean))
(For
(Identifier)
(Identifier)
(Other "in"
(RangeExpression
(IntegerLiteral)
(Other "..")
(IntegerLiteral)))
(Boolean)))

View File

@ -1,28 +1,29 @@
(Program
{+(AnonymousFunction
(ExpressionStatements
(Params
(Identifier))
(Binary
{+(MethodCall
(Identifier)
(Params
(Identifier))
(Binary
(Identifier)
(Other "+")
(IntegerLiteral)))+}
{-(MethodCall
(Identifier)
(Object))-}
{-(MethodCall
(Identifier)
(Identifier))-}
{-(MethodCall
(Identifier)
(Params
(Identifier)
(KeywordParameter
(Identifier)
(Other "+")
(IntegerLiteral))))+}
{-(AnonymousFunction
(ExpressionStatements))-}
{-(AnonymousFunction
(ExpressionStatements
(Identifier)))-}
{-(AnonymousFunction
(ExpressionStatements
(Params
(Boolean))
(OptionalParameter
(Identifier)
(KeywordParameter
(Identifier)
(Boolean))
(OptionalParameter
(Identifier)
(Identifier)))
(IntegerLiteral)))-}
(Identifier)))
(IntegerLiteral))-}
{-(AnonymousFunction
(ExpressionStatements))-}
{-(AnonymousFunction

View File

@ -1,25 +1,26 @@
(Program
{+(AnonymousFunction
(ExpressionStatements))+}
{+(AnonymousFunction
(ExpressionStatements
(Identifier)))+}
(AnonymousFunction
(ExpressionStatements
(Params
{ (Identifier)
->(Identifier) }
{+(KeywordParameter
(Identifier)
(Boolean))+}
{+(OptionalParameter
(Identifier)
(Identifier))+})
{+(IntegerLiteral)+}
{-(Binary
{+(MethodCall
(Identifier)
(Object))+}
{+(MethodCall
(Identifier)
(Identifier))+}
(MethodCall
(Identifier)
(Params
{ (Identifier)
->(Identifier) }
{+(KeywordParameter
(Identifier)
(Other "+")
(IntegerLiteral))-}))
(Boolean))+}
{+(OptionalParameter
(Identifier)
(Identifier))+})
{+(IntegerLiteral)+}
{-(Binary
(Identifier)
(Other "+")
(IntegerLiteral))-})
{+(AnonymousFunction
(ExpressionStatements))+}
{+(AnonymousFunction

View File

@ -1,20 +1,21 @@
(Program
(AnonymousFunction
(ExpressionStatements))
(AnonymousFunction
(ExpressionStatements
(Identifier)))
(AnonymousFunction
(ExpressionStatements
(Params
(MethodCall
(Identifier)
(Object))
(MethodCall
(Identifier)
(Identifier))
(MethodCall
(Identifier)
(Params
(Identifier)
(KeywordParameter
(Identifier)
(KeywordParameter
(Identifier)
(Boolean))
(OptionalParameter
(Identifier)
(Identifier)))
(IntegerLiteral)))
(Boolean))
(OptionalParameter
(Identifier)
(Identifier)))
(IntegerLiteral))
(AnonymousFunction
(ExpressionStatements))
(AnonymousFunction

View File

@ -1,9 +1,9 @@
(Program
(AnonymousFunction
(ExpressionStatements
(Params
(Identifier))
(Binary
(Identifier)
(Other "+")
(IntegerLiteral)))))
(MethodCall
(Identifier)
(Params
(Identifier))
(Binary
(Identifier)
(Other "+")
(IntegerLiteral))))

View File

@ -1,3 +1,7 @@
case foo
when bar
end
case
when true; 'foo'
end

View File

@ -1,4 +1,7 @@
case foo
when bar
baz
when a, b
else
bat
end

View File

@ -4,4 +4,11 @@
(When
(Args
(Identifier))
(Identifier))))-}
(Identifier)
(When
(Args
(Identifier))
(Args
(Identifier))
(Else
(Identifier))))))-}

View File

@ -4,4 +4,16 @@
(When
(Args
(Identifier))
{+(Identifier)+})))
{+(Identifier)+}
{+(When
(Args
(Identifier))
(Args
(Identifier))
(Else
(Identifier)))+}))
{-(Case
(When
(Args
(Boolean))
(StringLiteral)))-})

View File

@ -4,4 +4,16 @@
(When
(Args
(Identifier))
{-(Identifier)-})))
{-(Identifier)-}
{-(When
(Args
(Identifier))
(Args
(Identifier))
(Else
(Identifier)))-}))
{+(Case
(When
(Args
(Boolean))
(StringLiteral)))+})

View File

@ -3,4 +3,9 @@
(Identifier)
(When
(Args
(Identifier)))))
(Identifier))))
(Case
(When
(Args
(Boolean))
(StringLiteral))))

View File

@ -4,4 +4,11 @@
(When
(Args
(Identifier))
(Identifier))))
(Identifier)
(When
(Args
(Identifier))
(Args
(Identifier))
(Else
(Identifier))))))

@ -1 +1 @@
Subproject commit 45bbc5aff11ac5d4364b024d5b8693c297ee9ebb
Subproject commit 415584f7833c49bf06504c14b8fe7b613ae81fa1