Skip to content

Commit 9636212

Browse files
committed
Fix issue with calling generics
Issue #80 identified a case where the resolver would hang when calling a generic function with a parameter whose name matched the name of the argument. This occurred due to the order of resolution. Since we resolved bindings in a depth-first fashion, we simply ended up resolving a generic parameter to itself. One way to resolve this would have been to synthesize new names for each parameter in the scope of a local binding. But generating names and ensuring they are all unique is annoying. Instead, we switch the order of resolution. When binding generic args, we first resolve the arguments before traversing the body. That is, for a replacement series int -> x -> x We previously did int -> (x -> x) whereas now we do (int -> x) -> x Since the top-level (LHS) is always concrete, this process must terminate.
1 parent d0dad49 commit 9636212

File tree

2 files changed

+22
-14
lines changed

2 files changed

+22
-14
lines changed

example/cddl-files/issue80-min.cddl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
main = test<int, int>
2+
set<x> = [x]
3+
test<x, x1> = [
4+
1,
5+
x,
6+
set<x>
7+
]
8+

src/Codec/CBOR/Cuddle/CDDL/Resolve.hs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
-- generic arguments bound.
2626
module Codec.CBOR.Cuddle.CDDL.Resolve (
2727
buildResolvedCTree,
28-
monoCTree,
2928
buildRefCTree,
3029
asMap,
3130
buildMonoCTree,
@@ -323,10 +322,10 @@ postludeBinding =
323322
, (Name "null" mempty, PTNil)
324323
]
325324

326-
data BindingEnv poly f = BindingEnv
325+
data BindingEnv poly f g = BindingEnv
327326
{ global :: Map.Map Name (poly (CTree.Node f))
328327
-- ^ Global name bindings via 'RuleDef'
329-
, local :: Map.Map Name (CTree.Node f)
328+
, local :: Map.Map Name (CTree.Node g)
330329
-- ^ Local bindings for generic parameters
331330
}
332331
deriving (Generic)
@@ -354,7 +353,7 @@ deriving instance Eq (CTreeRoot DistRef)
354353
instance Hashable (CTreeRoot DistRef)
355354

356355
resolveRef ::
357-
BindingEnv (ParametrisedWith [Name]) OrRef ->
356+
BindingEnv (ParametrisedWith [Name]) OrRef OrRef ->
358357
CTree.Node OrRef ->
359358
Either NameResolutionFailure (DistRef (CTree DistRef))
360359
resolveRef env (It a) = DIt <$> resolveCTree env a
@@ -375,7 +374,7 @@ resolveRef env (Ref n args) = case Map.lookup n postludeBinding of
375374
Nothing -> Left $ UnboundReference n
376375

377376
resolveCTree ::
378-
BindingEnv (ParametrisedWith [Name]) OrRef ->
377+
BindingEnv (ParametrisedWith [Name]) OrRef OrRef ->
379378
CTree OrRef ->
380379
Either NameResolutionFailure (CTree DistRef)
381380
resolveCTree e = CTree.traverseCTree (resolveRef e)
@@ -407,7 +406,7 @@ deriving instance
407406
Show (poly (CTree.Node MonoRef)) =>
408407
Show (CTreeRoot' poly MonoRef)
409408

410-
type MonoEnv = BindingEnv (ParametrisedWith [Name]) DistRef
409+
type MonoEnv = BindingEnv (ParametrisedWith [Name]) DistRef MonoRef
411410

412411
-- | We introduce additional bindings in the state
413412
type MonoState = Map.Map Name (CTree.Node MonoRef)
@@ -432,10 +431,10 @@ newtype MonoM a = MonoM
432431
deriving
433432
( HasSource
434433
"local"
435-
(Map.Map Name (CTree.Node DistRef))
434+
(Map.Map Name (CTree.Node MonoRef))
436435
, HasReader
437436
"local"
438-
(Map.Map Name (CTree.Node DistRef))
437+
(Map.Map Name (CTree.Node MonoRef))
439438
)
440439
via Field
441440
"local"
@@ -490,11 +489,12 @@ synthMono n@(Name origName _) args =
490489
Just (Unparametrised _) -> throwNR $ MismatchingArgs n []
491490
Just (Parametrised r params') ->
492491
if length params' == length args
493-
then
494-
let localBinds = Map.fromList $ zip params' args
495-
in Reader.local @"local" (Map.union localBinds) $ do
496-
foo <- resolveGenericRef r
497-
modify @"synth" $ Map.insert fresh foo
492+
then do
493+
rargs <- traverse resolveGenericRef args
494+
let localBinds = Map.fromList $ zip params' rargs
495+
Reader.local @"local" (Map.union localBinds) $ do
496+
foo <- resolveGenericRef r
497+
modify @"synth" $ Map.insert fresh foo
498498
else throwNR $ MismatchingArgs n params'
499499
Nothing -> throwNR $ UnboundReference n
500500
pure fresh
@@ -512,7 +512,7 @@ resolveGenericRef (RuleRef n margs) =
512512
resolveGenericRef (GenericRef n) = do
513513
localBinds <- ask @"local"
514514
case Map.lookup n localBinds of
515-
Just node -> resolveGenericRef node
515+
Just node -> pure node
516516
Nothing -> throwNR $ UnboundReference n
517517

518518
resolveGenericCTree ::

0 commit comments

Comments
 (0)