elm-review/tests/Simplify/AstHelpers.elm

1035 lines
32 KiB
Elm
Raw Normal View History

2023-06-25 21:01:32 +03:00
module Simplify.AstHelpers exposing
( boolToString
, declarationListBindings
, emptyStringAsString
, getBool
, getBooleanPattern
, getCollapsedCons
, getListLiteral
, getListSingleton
, getListSingletonCall
, getNotFunction
, getOrder
, getSpecificFunction
, getSpecificFunctionCall
, getSpecificReducedFunction
, getSpecificReducedFunctionCall
, getSpecificValueOrFunction
, getTuple
, getTypeExposeIncludingVariants
, getUncomputedNumberValue
, isBinaryOperation
, isEmptyList
, isIdentity
, isListLiteral
, isSpecificBool
, isSpecificCall
, isSpecificValueOrFunction
, isTupleFirstAccess
, isTupleSecondAccess
, letDeclarationListBindings
, moduleNameFromString
, nameOfExpose
, orderToString
, patternBindings
, patternListBindings
, qualifiedToString
, removeParens
, removeParensFromPattern
)
2022-09-01 17:15:28 +03:00
2023-06-25 21:01:32 +03:00
import Elm.Syntax.Declaration as Declaration exposing (Declaration)
import Elm.Syntax.Exposing as Exposing
2022-09-01 17:15:28 +03:00
import Elm.Syntax.Expression as Expression exposing (Expression)
2023-06-25 21:01:32 +03:00
import Elm.Syntax.ModuleName exposing (ModuleName)
import Elm.Syntax.Node as Node exposing (Node(..))
2022-09-01 17:15:28 +03:00
import Elm.Syntax.Pattern as Pattern exposing (Pattern)
2023-06-25 21:01:32 +03:00
import Elm.Syntax.Range exposing (Range)
import Review.ModuleNameLookupTable as ModuleNameLookupTable exposing (ModuleNameLookupTable)
import Set exposing (Set)
import Simplify.Infer as Infer
import Simplify.Normalize as Normalize
2022-09-01 17:15:28 +03:00
removeParens : Node Expression -> Node Expression
removeParens node =
case Node.value node of
Expression.ParenthesizedExpression expr ->
removeParens expr
_ ->
node
removeParensFromPattern : Node Pattern -> Node Pattern
removeParensFromPattern node =
case Node.value node of
Pattern.ParenthesizedPattern pattern ->
removeParensFromPattern pattern
_ ->
node
2023-06-25 21:01:32 +03:00
isSpecificValueOrFunction : ModuleName -> String -> ModuleNameLookupTable -> Node Expression -> Bool
isSpecificValueOrFunction moduleName fnName lookupTable node =
case removeParens node of
Node noneRange (Expression.FunctionOrValue _ foundFnName) ->
(foundFnName == fnName)
&& (ModuleNameLookupTable.moduleNameAt lookupTable noneRange == Just moduleName)
_ ->
False
getSpecificValueOrFunction : ( ModuleName, String ) -> ModuleNameLookupTable -> Node Expression -> Maybe { fnRange : Range }
getSpecificValueOrFunction ( moduleName, fnName ) lookupTable node =
case removeParens node of
Node noneRange (Expression.FunctionOrValue _ foundFnName) ->
if
(foundFnName == fnName)
&& (ModuleNameLookupTable.moduleNameAt lookupTable noneRange == Just moduleName)
then
Just { fnRange = noneRange }
else
Nothing
_ ->
Nothing
isSpecificCall : ModuleName -> String -> ModuleNameLookupTable -> Node Expression -> Bool
isSpecificCall moduleName fnName lookupTable node =
case Node.value (removeParens node) of
Expression.Application ((Node noneRange (Expression.FunctionOrValue _ foundFnName)) :: _ :: []) ->
(foundFnName == fnName)
&& (ModuleNameLookupTable.moduleNameAt lookupTable noneRange == Just moduleName)
_ ->
False
getListSingleton : ModuleNameLookupTable -> Node Expression -> Maybe { element : Node Expression }
getListSingleton lookupTable baseNode =
case Node.value (removeParens baseNode) of
Expression.ListExpr [ element ] ->
Just { element = element }
Expression.ListExpr _ ->
Nothing
_ ->
getListSingletonCall lookupTable baseNode
getListSingletonCall : ModuleNameLookupTable -> Node Expression -> Maybe { element : Node Expression }
getListSingletonCall lookupTable expressionNode =
case getSpecificFunctionCall ( [ "List" ], "singleton" ) lookupTable expressionNode of
Just singletonCall ->
case singletonCall.argsAfterFirst of
[] ->
Just { element = singletonCall.firstArg }
_ :: _ ->
Nothing
Nothing ->
Nothing
getSpecificFunction : ( ModuleName, String ) -> ModuleNameLookupTable -> Node Expression -> Maybe Range
getSpecificFunction ( moduleName, name ) lookupTable baseNode =
case removeParens baseNode of
Node fnRange (Expression.FunctionOrValue _ foundName) ->
if
(foundName == name)
&& (ModuleNameLookupTable.moduleNameAt lookupTable fnRange == Just moduleName)
then
Just fnRange
else
Nothing
_ ->
Nothing
getSpecificFunctionCall :
( ModuleName, String )
-> ModuleNameLookupTable
-> Node Expression
->
Maybe
{ nodeRange : Range
, fnRange : Range
, firstArg : Node Expression
, argsAfterFirst : List (Node Expression)
}
getSpecificFunctionCall ( moduleName, name ) lookupTable baseNode =
getFunctionCall baseNode
|> Maybe.andThen
(\call ->
if
(call.fnName /= name)
|| (ModuleNameLookupTable.moduleNameAt lookupTable call.fnRange /= Just moduleName)
then
Nothing
else
Just
{ nodeRange = call.nodeRange
, fnRange = call.fnRange
, firstArg = call.firstArg
, argsAfterFirst = call.argsAfterFirst
}
)
getFunctionCall :
Node Expression
->
Maybe
{ nodeRange : Range
, fnName : String
, fnRange : Range
, firstArg : Node Expression
, argsAfterFirst : List (Node Expression)
}
getFunctionCall baseNode =
case Node.value (removeParens baseNode) of
Expression.Application ((Node fnRange (Expression.FunctionOrValue _ fnName)) :: firstArg :: argsAfterFirst) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, firstArg = firstArg
, argsAfterFirst = argsAfterFirst
}
Expression.OperatorApplication "|>" _ firstArg fedFunction ->
case fedFunction of
Node fnRange (Expression.FunctionOrValue _ fnName) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, firstArg = firstArg
, argsAfterFirst = []
}
Node _ (Expression.Application ((Node fnRange (Expression.FunctionOrValue _ fnName)) :: argsAfterFirst)) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, firstArg = firstArg
, argsAfterFirst = argsAfterFirst
}
_ ->
Nothing
Expression.OperatorApplication "<|" _ fedFunction firstArg ->
case fedFunction of
Node fnRange (Expression.FunctionOrValue _ fnName) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, firstArg = firstArg
, argsAfterFirst = []
}
Node _ (Expression.Application ((Node fnRange (Expression.FunctionOrValue _ fnName)) :: argsAfterFirst)) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, firstArg = firstArg
, argsAfterFirst = argsAfterFirst
}
_ ->
Nothing
_ ->
Nothing
getCollapsedValueOrFunction :
Node Expression
->
Maybe
{ nodeRange : Range
, fnName : String
, fnRange : Range
, args : List (Node Expression)
}
getCollapsedValueOrFunction baseNode =
let
step :
{ firstArg : Node Expression, argsAfterFirst : List (Node Expression), fed : Node Expression }
-> Maybe { nodeRange : Range, fnRange : Range, fnName : String, args : List (Node Expression) }
step layer =
Maybe.map
(\fed ->
{ nodeRange = Node.range baseNode
, fnRange = fed.fnRange
, fnName = fed.fnName
, args = fed.args ++ (layer.firstArg :: layer.argsAfterFirst)
}
)
(getCollapsedValueOrFunction layer.fed)
in
case removeParens baseNode of
Node fnRange (Expression.FunctionOrValue _ fnName) ->
Just
{ nodeRange = Node.range baseNode
, fnRange = fnRange
, fnName = fnName
, args = []
}
Node _ (Expression.Application (fed :: firstArg :: argsAfterFirst)) ->
step
{ fed = fed
, firstArg = firstArg
, argsAfterFirst = argsAfterFirst
}
Node _ (Expression.OperatorApplication "|>" _ firstArg fed) ->
step
{ fed = fed
, firstArg = firstArg
, argsAfterFirst = []
}
Node _ (Expression.OperatorApplication "<|" _ fed firstArg) ->
step
{ fed = fed
, firstArg = firstArg
, argsAfterFirst = []
}
_ ->
Nothing
getNotFunction : ModuleNameLookupTable -> Node Expression -> Maybe Range
getNotFunction lookupTable baseNode =
getSpecificFunction ( [ "Basics" ], "not" ) lookupTable baseNode
isTupleFirstAccess : ModuleNameLookupTable -> Node Expression -> Bool
isTupleFirstAccess lookupTable expressionNode =
case getSpecificReducedFunction ( [ "Tuple" ], "first" ) lookupTable expressionNode of
Just _ ->
True
Nothing ->
isTupleFirstPatternLambda expressionNode
isTupleSecondAccess : ModuleNameLookupTable -> Node Expression -> Bool
isTupleSecondAccess lookupTable expressionNode =
case getSpecificReducedFunction ( [ "Tuple" ], "second" ) lookupTable expressionNode of
Just _ ->
True
Nothing ->
isTupleSecondPatternLambda expressionNode
isTupleFirstPatternLambda : Node Expression -> Bool
isTupleFirstPatternLambda expressionNode =
case Node.value (removeParens expressionNode) of
Expression.LambdaExpression lambda ->
case lambda.args of
[ Node _ (Pattern.TuplePattern [ Node _ (Pattern.VarPattern firstVariableName), _ ]) ] ->
case Node.value lambda.expression of
Expression.FunctionOrValue [] resultName ->
resultName == firstVariableName
_ ->
False
_ ->
False
_ ->
False
isTupleSecondPatternLambda : Node Expression -> Bool
isTupleSecondPatternLambda expressionNode =
case Node.value (removeParens expressionNode) of
Expression.LambdaExpression lambda ->
case lambda.args of
[ Node _ (Pattern.TuplePattern [ _, Node _ (Pattern.VarPattern firstVariableName) ]) ] ->
case Node.value lambda.expression of
Expression.FunctionOrValue [] resultName ->
resultName == firstVariableName
_ ->
False
_ ->
False
_ ->
False
getUncomputedNumberValue : Node Expression -> Maybe Float
getUncomputedNumberValue node =
case Node.value (removeParens node) of
Expression.Integer n ->
Just (toFloat n)
Expression.Hex n ->
Just (toFloat n)
Expression.Floatable n ->
Just n
Expression.Negation expr ->
Maybe.map negate (getUncomputedNumberValue expr)
_ ->
Nothing
isIdentity : ModuleNameLookupTable -> Node Expression -> Bool
isIdentity lookupTable baseNode =
let
node : Node Expression
node =
removeParens baseNode
in
case Node.value node of
Expression.FunctionOrValue _ "identity" ->
ModuleNameLookupTable.moduleNameFor lookupTable node == Just [ "Basics" ]
Expression.LambdaExpression { args, expression } ->
case args of
arg :: [] ->
case getVarPattern arg of
Just patternName ->
getExpressionName expression
== Just patternName
_ ->
False
_ ->
False
_ ->
False
{-| Parses variables and lambdas that are reducible to a variable
-}
getSpecificReducedFunction : ( ModuleName, String ) -> ModuleNameLookupTable -> Node Expression -> Maybe { fnRange : Range }
getSpecificReducedFunction ( moduleName, name ) lookupTable expressionNode =
Maybe.andThen
(\reducedFunction ->
if
(reducedFunction.fnName /= name)
|| (ModuleNameLookupTable.moduleNameAt lookupTable reducedFunction.fnRange /= Just moduleName)
then
Nothing
else
Just { fnRange = reducedFunction.fnRange }
)
(getReducedFunction expressionNode)
{-| Parses variables and lambdas that are reducible to a variable
-}
getReducedFunction : Node Expression -> Maybe { fnRange : Range, fnName : String }
getReducedFunction expressionNode =
case removeParens expressionNode of
Node fnRange (Expression.FunctionOrValue _ fnName) ->
Just { fnRange = fnRange, fnName = fnName }
_ ->
Maybe.andThen
(\reducedLambdaToCall ->
case ( reducedLambdaToCall.lambdaPatterns, reducedLambdaToCall.callArguments ) of
( [], [] ) ->
Just { fnRange = reducedLambdaToCall.fnRange, fnName = reducedLambdaToCall.fnName }
( _ :: _, [] ) ->
Nothing
( [], _ :: _ ) ->
Nothing
( _ :: _, _ :: _ ) ->
Nothing
)
(getReducedLambdaToCall expressionNode)
{-| Parses calls and lambdas that are reducible to a call
-}
getSpecificReducedFunctionCall :
( ModuleName, String )
-> ModuleNameLookupTable
-> Node Expression
->
Maybe
{ nodeRange : Range
, fnRange : Range
, firstArg : Node Expression
, argsAfterFirst : List (Node Expression)
}
getSpecificReducedFunctionCall ( moduleName, name ) lookupTable expressionNode =
case getSpecificFunctionCall ( moduleName, name ) lookupTable expressionNode of
Just call ->
Just call
Nothing ->
Maybe.andThen
(\reducedLambdaToCall ->
case ( reducedLambdaToCall.lambdaPatterns, reducedLambdaToCall.callArguments ) of
( [], [] ) ->
Nothing
( _ :: _, [] ) ->
Nothing
( _ :: _, _ :: _ ) ->
Nothing
( [], firstArg :: argsAfterFirst ) ->
Just
{ nodeRange = reducedLambdaToCall.nodeRange
, fnRange = reducedLambdaToCall.fnRange
, firstArg = firstArg
, argsAfterFirst = argsAfterFirst
}
)
(getSpecificReducedLambdaToCall ( moduleName, name ) lookupTable expressionNode)
getSpecificReducedLambdaToCall :
( ModuleName, String )
-> ModuleNameLookupTable
-> Node Expression
->
Maybe
{ nodeRange : Range
, fnRange : Range
, callArguments : List (Node Expression)
, lambdaPatterns : List (Node Pattern)
}
getSpecificReducedLambdaToCall ( moduleName, name ) lookupTable expressionNode =
getReducedLambdaToCall expressionNode
|> Maybe.andThen
(\reducedLambdaToCall ->
if
(reducedLambdaToCall.fnName /= name)
|| (ModuleNameLookupTable.moduleNameAt lookupTable reducedLambdaToCall.fnRange /= Just moduleName)
then
Nothing
else
Just
{ nodeRange = reducedLambdaToCall.nodeRange
, fnRange = reducedLambdaToCall.fnRange
, callArguments = reducedLambdaToCall.callArguments
, lambdaPatterns = reducedLambdaToCall.lambdaPatterns
}
)
getReducedLambdaToCall :
Node Expression
->
Maybe
{ nodeRange : Range
, fnName : String
, fnRange : Range
, callArguments : List (Node Expression)
, lambdaPatterns : List (Node Pattern)
}
getReducedLambdaToCall expressionNode =
-- maybe a version of this is better located in Normalize?
case getCollapsedLambda expressionNode of
Just lambda ->
case getCollapsedValueOrFunction lambda.expression of
Just call ->
let
( reducedCallArguments, reducedLambdaPatterns ) =
drop2EndingsWhile
(\( argument, pattern ) ->
case Node.value (removeParens argument) of
Expression.FunctionOrValue [] argument0Name ->
case getVarPattern pattern of
Just pattern0Name ->
pattern0Name == argument0Name
_ ->
False
_ ->
False
)
( call.args
, lambda.patterns
)
in
Just
{ nodeRange = Node.range expressionNode
, fnName = call.fnName
, fnRange = call.fnRange
, callArguments = reducedCallArguments
, lambdaPatterns = reducedLambdaPatterns
}
Nothing ->
Nothing
_ ->
Nothing
{-| Remove elements at the end of both given lists, then repeat for the previous elements until a given test returns False
-}
drop2EndingsWhile : (( a, b ) -> Bool) -> ( List a, List b ) -> ( List a, List b )
drop2EndingsWhile shouldDrop ( aList, bList ) =
let
( reducedArgumentsReverse, reducedPatternsReverse ) =
drop2BeginningsWhile
shouldDrop
( List.reverse aList
, List.reverse bList
)
in
( List.reverse reducedArgumentsReverse, List.reverse reducedPatternsReverse )
drop2BeginningsWhile : (( a, b ) -> Bool) -> ( List a, List b ) -> ( List a, List b )
drop2BeginningsWhile shouldDrop listPair =
case listPair of
( [], bList ) ->
( [], bList )
( aList, [] ) ->
( aList, [] )
( aHead :: aTail, bHead :: bTail ) ->
if shouldDrop ( aHead, bHead ) then
drop2BeginningsWhile shouldDrop ( aTail, bTail )
else
( aHead :: aTail, bHead :: bTail )
getCollapsedLambda : Node Expression -> Maybe { patterns : List (Node Pattern), expression : Node Expression }
getCollapsedLambda expressionNode =
case Node.value (removeParens expressionNode) of
Expression.LambdaExpression lambda ->
case getCollapsedLambda lambda.expression of
Nothing ->
Just
{ patterns = lambda.args
, expression = lambda.expression
}
Just innerCollapsedLambda ->
Just
{ patterns = lambda.args ++ innerCollapsedLambda.patterns
, expression = innerCollapsedLambda.expression
}
_ ->
Nothing
getVarPattern : Node Pattern -> Maybe String
getVarPattern node =
case Node.value node of
Pattern.VarPattern name ->
Just name
Pattern.ParenthesizedPattern pattern ->
getVarPattern pattern
_ ->
Nothing
patternListBindings : List (Node Pattern) -> Set String
patternListBindings patterns =
List.foldl
(\(Node _ pattern) soFar -> Set.union soFar (patternBindings pattern))
Set.empty
patterns
{-| Recursively find all bindings in a pattern.
-}
patternBindings : Pattern -> Set String
patternBindings pattern =
case pattern of
Pattern.ListPattern patterns ->
patternListBindings patterns
Pattern.TuplePattern patterns ->
patternListBindings patterns
Pattern.RecordPattern patterns ->
Set.fromList (List.map Node.value patterns)
Pattern.NamedPattern _ patterns ->
patternListBindings patterns
Pattern.UnConsPattern (Node _ headPattern) (Node _ tailPattern) ->
Set.union (patternBindings tailPattern) (patternBindings headPattern)
Pattern.VarPattern name ->
Set.singleton name
Pattern.AsPattern (Node _ pattern_) (Node _ name) ->
Set.insert name (patternBindings pattern_)
Pattern.ParenthesizedPattern (Node _ inParens) ->
patternBindings inParens
Pattern.AllPattern ->
Set.empty
Pattern.UnitPattern ->
Set.empty
Pattern.CharPattern _ ->
Set.empty
Pattern.StringPattern _ ->
Set.empty
Pattern.IntPattern _ ->
Set.empty
Pattern.HexPattern _ ->
Set.empty
Pattern.FloatPattern _ ->
Set.empty
declarationListBindings : List (Node Declaration) -> Set String
declarationListBindings declarationList =
declarationList
|> List.map (\(Node _ declaration) -> declarationBindings declaration)
|> List.foldl (\bindings soFar -> Set.union soFar bindings) Set.empty
declarationBindings : Declaration -> Set String
declarationBindings declaration =
case declaration of
Declaration.CustomTypeDeclaration variantType ->
variantType.constructors
|> List.map (\(Node _ variant) -> Node.value variant.name)
|> Set.fromList
Declaration.FunctionDeclaration functionDeclaration ->
Set.singleton
(Node.value (Node.value functionDeclaration.declaration).name)
_ ->
Set.empty
letDeclarationBindings : Expression.LetDeclaration -> Set String
letDeclarationBindings letDeclaration =
case letDeclaration of
Expression.LetFunction fun ->
Set.singleton
(fun.declaration |> Node.value |> .name |> Node.value)
Expression.LetDestructuring (Node _ pattern) _ ->
patternBindings pattern
letDeclarationListBindings : List (Node Expression.LetDeclaration) -> Set String
letDeclarationListBindings letDeclarationList =
letDeclarationList
|> List.map
(\(Node _ declaration) -> letDeclarationBindings declaration)
|> List.foldl (\bindings soFar -> Set.union soFar bindings) Set.empty
getExpressionName : Node Expression -> Maybe String
getExpressionName node =
case Node.value (removeParens node) of
Expression.FunctionOrValue [] name ->
Just name
_ ->
Nothing
isListLiteral : Node Expression -> Bool
isListLiteral node =
case Node.value node of
Expression.ListExpr _ ->
True
_ ->
False
getListLiteral : Node Expression -> Maybe (List (Node Expression))
getListLiteral expressionNode =
case Node.value expressionNode of
Expression.ListExpr list ->
Just list
_ ->
Nothing
getCollapsedCons : Node Expression -> Maybe { consed : List (Node Expression), tail : Node Expression }
getCollapsedCons expressionNode =
case Node.value (removeParens expressionNode) of
Expression.OperatorApplication "::" _ head tail ->
let
tailCollapsed : Maybe { consed : List (Node Expression), tail : Node Expression }
tailCollapsed =
getCollapsedCons tail
in
case tailCollapsed of
Nothing ->
Just { consed = [ head ], tail = tail }
Just tailCollapsedList ->
Just { consed = head :: tailCollapsedList.consed, tail = tailCollapsedList.tail }
_ ->
Nothing
getBool : ModuleNameLookupTable -> Node Expression -> Maybe Bool
getBool lookupTable expressionNode =
if isSpecificBool True lookupTable expressionNode then
Just True
else if isSpecificBool False lookupTable expressionNode then
Just False
else
Nothing
isSpecificBool : Bool -> ModuleNameLookupTable -> Node Expression -> Bool
isSpecificBool specificBool lookupTable expressionNode =
isSpecificValueOrFunction [ "Basics" ] (boolToString specificBool) lookupTable expressionNode
getTuple : Node Expression -> Maybe { range : Range, first : Node Expression, second : Node Expression }
getTuple expressionNode =
case Node.value expressionNode of
Expression.TupledExpression (first :: second :: []) ->
Just { range = Node.range expressionNode, first = first, second = second }
_ ->
Nothing
getBooleanPattern : ModuleNameLookupTable -> Node Pattern -> Maybe Bool
getBooleanPattern lookupTable node =
case Node.value node of
Pattern.NamedPattern { name } _ ->
case name of
"True" ->
if ModuleNameLookupTable.moduleNameFor lookupTable node == Just [ "Basics" ] then
Just True
else
Nothing
"False" ->
if ModuleNameLookupTable.moduleNameFor lookupTable node == Just [ "Basics" ] then
Just False
else
Nothing
_ ->
Nothing
Pattern.ParenthesizedPattern pattern ->
getBooleanPattern lookupTable pattern
_ ->
Nothing
getOrder : ModuleNameLookupTable -> Node Expression -> Maybe Order
getOrder lookupTable expression =
if isSpecificValueOrFunction [ "Basics" ] "LT" lookupTable expression then
Just LT
else if isSpecificValueOrFunction [ "Basics" ] "EQ" lookupTable expression then
Just EQ
else if isSpecificValueOrFunction [ "Basics" ] "GT" lookupTable expression then
Just GT
else
Nothing
isEmptyList : Node Expression -> Bool
isEmptyList node =
case Node.value (removeParens node) of
Expression.ListExpr [] ->
True
_ ->
False
isBinaryOperation : String -> Infer.Resources a -> Node Expression -> Bool
isBinaryOperation symbol checkInfo expression =
case expression |> Normalize.normalize checkInfo |> Node.value of
Expression.PrefixOperator operatorSymbol ->
operatorSymbol == symbol
Expression.LambdaExpression lambda ->
case lambda.args of
-- invalid syntax
[] ->
False
[ Node _ (Pattern.VarPattern element) ] ->
case Node.value lambda.expression of
Expression.Application [ Node _ (Expression.PrefixOperator operatorSymbol), Node _ (Expression.FunctionOrValue [] argument) ] ->
(operatorSymbol == symbol)
&& (argument == element)
-- no simple application
_ ->
False
[ Node _ (Pattern.VarPattern element), Node _ (Pattern.VarPattern soFar) ] ->
case Node.value lambda.expression of
Expression.Application [ Node _ (Expression.PrefixOperator operatorSymbol), Node _ (Expression.FunctionOrValue [] left), Node _ (Expression.FunctionOrValue [] right) ] ->
(operatorSymbol == symbol)
&& ((left == element && right == soFar)
|| (left == soFar && right == element)
)
Expression.OperatorApplication operatorSymbol _ (Node _ (Expression.FunctionOrValue [] left)) (Node _ (Expression.FunctionOrValue [] right)) ->
(operatorSymbol == symbol)
&& ((left == element && right == soFar)
|| (left == soFar && right == element)
)
_ ->
False
-- too many/unsimplified patterns
_ ->
False
-- not a known simple operator function
_ ->
False
getTypeExposeIncludingVariants : Exposing.TopLevelExpose -> Maybe String
getTypeExposeIncludingVariants expose =
case expose of
Exposing.InfixExpose _ ->
Nothing
Exposing.FunctionExpose _ ->
Nothing
Exposing.TypeOrAliasExpose _ ->
Nothing
Exposing.TypeExpose variantType ->
case variantType.open of
Nothing ->
Nothing
Just _ ->
Just variantType.name
nameOfExpose : Exposing.TopLevelExpose -> String
nameOfExpose topLevelExpose =
case topLevelExpose of
Exposing.FunctionExpose name ->
name
Exposing.TypeOrAliasExpose name ->
name
Exposing.InfixExpose name ->
name
Exposing.TypeExpose { name } ->
name
-- STRING
emptyStringAsString : String
emptyStringAsString =
"\"\""
boolToString : Bool -> String
boolToString bool =
if bool then
"True"
else
"False"
orderToString : Order -> String
orderToString order =
case order of
LT ->
"LT"
EQ ->
"EQ"
GT ->
"GT"
{-| Put a `ModuleName` and thing name together as a string.
If desired, call in combination with `qualify`
-}
qualifiedToString : ( ModuleName, String ) -> String
qualifiedToString ( moduleName, name ) =
if List.isEmpty moduleName then
name
else
moduleNameToString moduleName ++ "." ++ name
moduleNameToString : ModuleName -> String
moduleNameToString moduleName =
String.join "." moduleName
moduleNameFromString : String -> ModuleName
moduleNameFromString string =
String.split "." string