Skip to content

Commit

Permalink
Perform substitution in function signature queries
Browse files Browse the repository at this point in the history
  • Loading branch information
albertprz committed May 5, 2024
1 parent f98a2f2 commit 5d9c615
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 14 deletions.
68 changes: 64 additions & 4 deletions src/Components/Explorer/FunctionFilter.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import App.Parser.Common (token)
import App.Parser.FnDef (fnBody)
import App.Parser.Type (type')
import App.SyntaxTree.Common (Module, QVar(..), QVarOp)
import App.SyntaxTree.FnDef (FnBody(..), Object)
import App.SyntaxTree.Type (Type)
import App.SyntaxTree.FnDef (FnBody(..), FnSig, Object)
import App.SyntaxTree.Type (Type(..), TypeParam)
import Bookhound.Parser (runParser)
import Bookhound.ParserCombinators (is, someSepBy)
import Bookhound.Parsers.Char (comma)
import Bookhound.Parsers.String (betweenParens)
import Data.Array as Array
import Data.Map as Map
import Data.String.Utils as String

data FnFilter
Expand Down Expand Up @@ -69,8 +71,10 @@ termPredicate ctx fnFilter module' (SuggestionInfo info) =
evalExample info.fn args ctx == evalResult info.fn result ctx

isSignatureOf paramTypes returnType =
filterMap snd info.fnSig.params == paramTypes
&& (info.fnSig.returnType == Just returnType)
any (_ `matchesType` targetType) sourceType
where
sourceType = buildFnSigType info.fnSig
targetType = buildFunctionType paramTypes returnType

isNameLike :: forall a. Show a => a -> a -> Boolean
isNameLike x y =
Expand All @@ -89,3 +93,59 @@ evalResult (QVar module' _) result ctx =
hush $ evalExprInCtx ctx' result
where
ctx' = ctx { module' = unsafeFromJust module' }

buildFnSigType :: FnSig -> Maybe Type
buildFnSigType { params, returnType } =
buildFunctionType <$> traverse snd params <*> returnType

buildFunctionType :: Array Type -> Type -> Type
buildFunctionType paramTypes returnType =
ArrowTypeApply $ Array.snoc paramTypes returnType

countFnSigParams :: FnSig -> Int
countFnSigParams fnSig =
maybe zero countParams $ buildFnSigType fnSig

countParams :: Type -> Int
countParams = case _ of
TypeApply x xs -> sum $ map countParams (Array.cons x xs)
ArrowTypeApply xs -> sum $ map countParams xs
UnionTypeApply xs -> sum $ map countParams xs
ArrayTypeApply x -> countParams x
TypeParam' _ -> one
_ -> zero

matchesType :: Type -> Type -> Boolean
matchesType sourceType targetType =
replacedType == targetType
where
replacedType = replaceParams replacements sourceType
replacements = findParamReplacements (sourceType /\ targetType)

findParamReplacements :: (Type /\ Type) -> Map TypeParam Type
findParamReplacements = case _ of
TypeApply x xs /\ TypeApply y ys ->
Map.unions $ map findParamReplacements
$ Array.zip (Array.cons x xs) (Array.cons y ys)
ArrowTypeApply xs /\ ArrowTypeApply ys ->
Map.unions $ map findParamReplacements $ Array.zip xs ys
UnionTypeApply xs /\ ArrowTypeApply ys ->
Map.unions $ map findParamReplacements $ Array.zip xs ys
ArrayTypeApply x /\ ArrayTypeApply y ->
findParamReplacements (x /\ y)
TypeParam' param /\ targetType ->
Map.singleton param targetType
_ /\ _ -> Map.empty

replaceParams :: Map TypeParam Type -> Type -> Type
replaceParams replacements = case _ of
TypeApply x xs -> TypeApply (replace x) (map replace xs)
ArrowTypeApply xs -> ArrowTypeApply $ map replace xs
UnionTypeApply xs -> UnionTypeApply $ map replace xs
ArrayTypeApply x -> ArrayTypeApply $ replace x
TypeParam' param
| Just targetType <- Map.lookup param replacements -> targetType
| otherwise -> TypeParam' param
x -> x
where
replace x = replaceParams replacements x
9 changes: 7 additions & 2 deletions src/Components/Explorer/Renderer.purs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import App.AppM (AppM)
import App.AppStore (mkLocalContext)
import App.CSS.ClassNames (explorerContainer, formulaBox, functionContainer, functionDescription, functionDoc, functionFiltersContainer, functionRow, functionsList, invisibleContainer, termTypeLabel, validFormula)
import App.CSS.Ids (functionRowId)
import App.Components.Explorer.FunctionFilter (evalExample, parseFnFilter, termPredicate)
import App.Components.Explorer.FunctionFilter (FnFilter(..), countFnSigParams, evalExample, parseFnFilter, termPredicate)
import App.Components.Explorer.Handler (handleModuleTypeaheadOutput)
import App.Components.Explorer.Models (ExplorerAction(..), ExplorerState, Slots, _moduleTypeahead, allModules, functionFilterInputRef)
import App.Components.Typeahead as Typeahead
Expand Down Expand Up @@ -75,12 +75,17 @@ render { route, store, module', fnFilter, fnFilterText, selectedRow } =
, style "border-collapse: collapse"
, onKeyDown $ mkKeyAction TableKeyDown
]
(mapWithIndex renderFunctionRow infos)
(mapWithIndex renderFunctionRow sortedInfos)
]
where
maxExampleLen = alaF Max foldMap findExampleLength $ lines doc
doc = foldMap _.fnSig.doc selectedSuggestion
fn = map _.fn selectedSuggestion
sortedInfos
| Just (FnSignature _ _) <- fnFilter = Array.sortWith
(countFnSigParams <<< _.fnSig <<< unwrap)
infos
| otherwise = infos
infos = filter (termPredicate ctx fnFilter module')
$ filterMap (getSuggestionInfo ctx)
$ Array.fromFoldable
Expand Down
3 changes: 1 addition & 2 deletions src/Parser/Type.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ type' = defer \_ -> complexType <|> atom
where

typeApply = defer \_ ->
VarTypeApply <$> typeVar <*> argListOf type'
<|> (ParamTypeApply <$> typeParam <*> argListOf type')
TypeApply <$> (typeVar' <|> typeParam') <*> argListOf type'

arrow = defer \_ -> ArrowTypeApply <$> multipleSepBy (isToken "->")
(atom <|> betweenParens complexType)
Expand Down
5 changes: 3 additions & 2 deletions src/SyntaxTree/Type.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ newtype TypeParam = TypeParam Char
newtype TypeVar = TypeVar String

data Type
= VarTypeApply TypeVar (Array Type)
| ParamTypeApply TypeParam (Array Type)
= TypeApply Type (Array Type)
| ArrowTypeApply (Array Type)
| UnionTypeApply (Array Type)
| ArrayTypeApply Type
Expand All @@ -29,6 +28,8 @@ instance Show TypeVar where

derive instance Newtype TypeParam _

derive newtype instance Ord TypeParam

derive newtype instance EncodeJson TypeParam

instance DecodeJson TypeParam where
Expand Down
8 changes: 4 additions & 4 deletions src/Utils/SyntaxAtom.purs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ fnSigToSyntaxAtoms (QVar _ fnName) { params, returnType } =

typeToSyntaxAtoms :: Type -> Array SyntaxAtom
typeToSyntaxAtoms = case _ of
VarTypeApply x ys -> typeApply x ys
ParamTypeApply x ys -> typeApply x ys
TypeApply x ys -> typeApply x ys
ArrowTypeApply xs -> infixTypeApply "" xs
UnionTypeApply xs -> infixTypeApply "|" xs
ArrayTypeApply x -> wrapSquare $ typeToSyntaxAtoms x
Expand All @@ -80,8 +79,9 @@ typeToSyntaxAtoms = case _ of
var :: forall a. Show a => a -> SyntaxAtom
var = Cell' <<< show

typeApply :: forall a. Show a => a -> Array Type -> Array SyntaxAtom
typeApply x ys = [ var x, OtherText " " ]
typeApply :: Type -> Array Type -> Array SyntaxAtom
typeApply x ys = typeToSyntaxAtoms x
<> [ OtherText " " ]
<> wrapArgList (map typeToSyntaxAtoms ys)

infixTypeApply op =
Expand Down

0 comments on commit 5d9c615

Please sign in to comment.