Skip to content

Commit

Permalink
fix: extend available actions property test to cover typedefs, and fi…
Browse files Browse the repository at this point in the history
…x revealed bugs (#1040)
  • Loading branch information
brprice authored Jun 28, 2023
2 parents b662e66 + 88728cf commit f8944f6
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 152 deletions.
2 changes: 1 addition & 1 deletion primer/src/Primer/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ availableActions = curry3 $ logAPI (noError AvailableActions) $ \(sid, level, se
(editable, def) <- findASTTypeDef allTypeDefs sel.def
let getActions = case sel.node of
Nothing -> Available.forTypeDef
Just (TypeDefParamNodeSelection _) -> Available.forTypeDefParamNode
Just (TypeDefParamNodeSelection p) -> Available.forTypeDefParamNode p
Just (TypeDefConsNodeSelection s) -> case s.field of
Nothing -> Available.forTypeDefConsNode
Just field -> Available.forTypeDefConsFieldNode s.con field.index field.meta
Expand Down
27 changes: 18 additions & 9 deletions primer/src/Primer/Action.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ renameForall b zt = case target zt of
-- | Convert a high-level 'Available.NoInputAction' to a concrete sequence of 'ProgAction's.
toProgActionNoInput ::
DefMap ->
Either (ASTTypeDef a) ASTDef ->
Either (ASTTypeDef TypeMeta) ASTDef ->
Selection' ID ->
Available.NoInputAction ->
Either ActionError [ProgAction]
Expand Down Expand Up @@ -1088,14 +1088,23 @@ toProgActionNoInput defs def0 sel0 = \case
-- resulting in a new argument type. The result type is unchanged.
-- The cursor location is also unchanged.
-- e.g. A -> B -> C ==> A -> B -> ? -> C
id <- nodeID
def <- termDef
type_ <- case findType id $ astDefType def of
Just t -> pure t
Nothing -> case map fst $ findNodeWithParent id $ astDefExpr def of
Just (TypeNode t) -> pure t
Just sm -> Left $ NeedType sm
Nothing -> Left $ IDNotFound id
type_ <- case def0 of
Left def -> do
(tName, vcName, field) <- conFieldSel
let id = field.meta
vc <- maybeToEither (ValConNotFound tName vcName) $ find ((== vcName) . valConName) $ astTypeDefConstructors def
t <- maybeToEither (FieldIndexOutOfBounds vcName field.index) $ flip atMay field.index $ valConArgs vc
case findType id t of
Just t' -> pure $ forgetTypeMetadata t'
Nothing -> Left $ IDNotFound id
Right def -> do
id <- nodeID
forgetTypeMetadata <$> case findType id $ astDefType def of
Just t -> pure t
Nothing -> case map fst $ findNodeWithParent id $ astDefExpr def of
Just (TypeNode t) -> pure t
Just sm -> Left $ NeedType sm
Nothing -> Left $ IDNotFound id
l <- case type_ of
TFun _ a b -> pure $ NE.length $ fst $ unfoldFun a b
t -> Left $ NeedTFun t
Expand Down
15 changes: 11 additions & 4 deletions primer/src/Primer/Action/Available.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import Primer.Core (
Pattern (PatCon, PatPrim),
PrimCon (PrimChar, PrimInt),
TyConName,
TyVarName,
Type,
Type' (..),
TypeMeta,
Expand All @@ -84,7 +85,7 @@ import Primer.Core (
_typeMetaLens,
)
import Primer.Core.Transform (decomposeTAppCon)
import Primer.Core.Utils (forgetTypeMetadata, freeVars)
import Primer.Core.Utils (forgetTypeMetadata, freeVars, freeVarsTy)
import Primer.Def (
ASTDef (..),
DefMap,
Expand Down Expand Up @@ -367,20 +368,26 @@ forTypeDef l Editable tydefs defs tdName td =
)

forTypeDefParamNode ::
TyVarName ->
Level ->
Editable ->
TypeDefMap ->
DefMap ->
TyConName ->
ASTTypeDef TypeMeta ->
[Action]
forTypeDefParamNode _ NonEditable _ _ _ _ = mempty
forTypeDefParamNode l Editable tydefs defs tdName td =
forTypeDefParamNode _ _ NonEditable _ _ _ _ = mempty
forTypeDefParamNode paramName l Editable tydefs defs tdName td =
sortByPriority l $
[ Input RenameTypeParam
]
<> mwhen
(l == Expert && not (typeInUse tdName td tydefs defs))
( l == Expert
&& not
( typeInUse tdName td tydefs defs
|| any (elem paramName . freeVarsTy) (concatMap valConArgs $ astTypeDefConstructors td)
)
)
[NoInput DeleteTypeParam]

forTypeDefConsNode ::
Expand Down
5 changes: 3 additions & 2 deletions primer/src/Primer/Action/Errors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Data.Aeson (FromJSON (..), ToJSON (..))
import Primer.Action.Actions (Action)
import Primer.Action.Available qualified as Available
import Primer.Action.Movement (Movement)
import Primer.Core (Expr, GVarName, ID, LVarName, ModuleName, Pattern, TyConName, Type, Type', ValConName)
import Primer.Core (Expr, GVarName, ID, LVarName, ModuleName, Pattern, TyConName, Type', ValConName)
import Primer.JSON (CustomJSON (..), PrimerJSON)
import Primer.Typecheck.TypeError (TypeError)
import Primer.Zipper (SomeNode)
Expand Down Expand Up @@ -62,7 +62,7 @@ data ActionError
-- The extra unit is to avoid having two constructors with a single
-- TypeError field, breaking our MonadNestedError machinery...
ImportFailed () TypeError
| NeedTFun Type
| NeedTFun (Type' ())
| NeedType SomeNode
| NeedGlobal Available.Option
| NeedLocal Available.Option
Expand All @@ -78,5 +78,6 @@ data ActionError
| NeedTypeDefParamSelection
| NoNodeSelection
| ValConNotFound TyConName ValConName
| FieldIndexOutOfBounds ValConName Int
deriving stock (Eq, Show, Read, Generic)
deriving (FromJSON, ToJSON) via PrimerJSON ActionError
10 changes: 8 additions & 2 deletions primer/src/Primer/Action/ProgError.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,22 @@ data ProgError
| TypeDefNotFound TyConName
| TypeDefAlreadyExists TyConName
| TypeDefInUse TyConName
| -- | Cannot use a name twice in a type definition.
-- This includes
-- - clash between the type itself and a constructor
-- - clash between the type itself and a parameter
-- - clash between two constructors
-- - clash between two parameters
-- - clash between parameter and constructor
TypeDefModifyNameClash Name
| TypeParamInUse TyConName TyVarName
| ConNotFound ValConName
| ConAlreadyExists ValConName
| -- | We expected to see more arguments to a constructor than actually existed
-- (this should never happen in a well-typed program)
ConNotSaturated ValConName
| ParamNotFound TyVarName
| ParamAlreadyExists TyVarName
| NodeIDNotFound ID
| TyConParamClash Name
| ValConParamClash Name
| ActionError ActionError
| EvalError EvalError
Expand Down
Loading

0 comments on commit f8944f6

Please sign in to comment.