@@ -35,7 +35,7 @@ data MkFn a
3535 | MkFnNext (Maybe Ident) (a -> MkFn a)
3636
3737data BackendSemantics
38− = SemExtern (Qualified Ident) (Array ExternSpine) (Lazy BackendSemantics)
38+ = SemRef EvalRef (Array ExternSpine) (Lazy BackendSemantics)
3939 | SemLam (Maybe Ident) (BackendSemantics -> BackendSemantics)
4040 | SemMkFn (MkFn BackendSemantics)
4141 | SemMkEffectFn (MkFn BackendSemantics)
@@ -45,7 +45,7 @@ data BackendSemantics
4545 | SemEffectPure BackendSemantics
4646 | SemEffectDefer BackendSemantics
4747 | SemBranch (NonEmptyArray (SemConditional BackendSemantics)) (Lazy BackendSemantics)
48− | NeutLocal (Maybe Ident) Level (Maybe BackendSemantics)
48+ | NeutLocal (Maybe Ident) Level
4949 | NeutVar (Qualified Ident)
5050 | NeutStop (Qualified Ident)
5151 | NeutData (Qualified Ident) ConstructorType ProperName Ident (Array (Tuple String BackendSemantics))
@@ -162,7 +162,8 @@ type InlineDirectiveMap = Map EvalRef (Map InlineAccessor InlineDirective)
162162
163163newtype Env = Env
164164 { currentModule :: ModuleName
165− , evalExtern :: Env -> Qualified Ident -> Array ExternSpine -> Maybe BackendSemantics
165+ , evalExternRef :: Env -> Qualified Ident -> Maybe BackendSemantics
166+ , evalExternSpine :: Env -> Qualified Ident -> Array ExternSpine -> Maybe BackendSemantics
166167 , locals :: Array (LocalBinding BackendSemantics)
167168 , directives :: InlineDirectiveMap
168169 }
@@ -200,9 +201,18 @@ class Eval f where
200201 eval :: Env -> f -> BackendSemantics
201202
202203instance Eval f => Eval (BackendSyntax f) where
203− eval env = case _ of
204+ eval env@(Env e) = case _ of
204205 Var qual ->
205− evalExtern env qual []
206+ case e.evalExternSpine env qual [] of
207+ Just sem ->
208+ sem
209+ Nothing ->
210+ SemRef (EvalExtern qual) [] $ defer \_ ->
211+ case e.evalExternRef env qual of
212+ Just sem ->
213+ deref sem
214+ Nothing ->
215+ NeutVar qual
206216 Local ident lvl ->
207217 case lookupLocal env lvl of
208218 Just (One sem) -> sem
@@ -391,8 +401,8 @@ evalApp env hd spine = go env hd (List.fromFoldable spine)
391401 SemLam _ k, List.Cons arg args ->
392402 makeLet Nothing arg \nextArg ->
393403 go env' (k nextArg) args
394− SemExtern qual sp _, List.Cons arg args -> do
395− go env' (evalExtern env' qual (snocApp sp arg)) args
404+ SemRef ref sp sem, List.Cons arg args ->
405+ go env' (evalRef env' ref sp (ExternApp [ arg ]) sem) args
396406 SemLet ident val k, args ->
397407 SemLet ident val \nextVal ->
398408 makeLet Nothing (k nextVal) \nextFn ->
@@ -410,9 +420,9 @@ evalUncurriedApp :: Env -> BackendSemantics -> Spine BackendSemantics -> Backend
410420evalUncurriedApp env hd spine = case hd of
411421 SemMkFn mk ->
412422 evalUncurriedBeta NeutUncurriedApp mk spine
413− SemExtern qual sp _ ->
423+ SemRef ref sp sem ->
414424 guardFailOver identity spine \spine' ->
415− evalExtern env qual (Array.snoc sp (ExternUncurriedApp spine'))
425+ evalRef env ref sp (ExternUncurriedApp spine') sem
416426 SemLet ident val k ->
417427 SemLet ident val \nextVal ->
418428 makeLet Nothing (k nextVal) \nextFn ->
@@ -490,8 +500,8 @@ neutralApp hd spine
490500evalAccessor :: Env -> BackendSemantics -> BackendAccessor -> BackendSemantics
491501evalAccessor initEnv initLhs accessor =
492502 evalAssocLet initEnv initLhs \env lhs -> case lhs of
493− SemExtern qual spine _ ->
494− evalExtern env qual $ Array.snoc spine (ExternAccessor accessor)
503+ SemRef ref spine sem ->
504+ evalRef env ref spine (ExternAccessor accessor) sem
495505 NeutLit (LitRecord props)
496506 | GetProp prop <- accessor
497507 , Just sem <- Array.findMap (\(Prop p v) -> guard (p == prop) $> v) props ->
@@ -532,7 +542,7 @@ evalBranches _ initConds initDef = go [] (NonEmptyArray.toArray initConds) initD
532542 go acc conds def = case Array.uncons conds of
533543 Just { head, tail } ->
534544 case head of
535− SemConditional c t -> case force c of
545+ SemConditional c t -> case deref (force c) of
536546 NeutLit (LitBoolean didMatch)
537547 | didMatch -> go acc [] t
538548 | otherwise -> go acc tail def
@@ -591,9 +601,9 @@ evalAssocLet2 env sem1 sem2 go =
591601
592602makeLet :: Maybe Ident -> BackendSemantics -> (BackendSemantics -> BackendSemantics) -> BackendSemantics
593603makeLet ident binding go = case binding of
594− SemExtern _ [] _ ->
604+ SemRef _ [] _ ->
595605 go binding
596− NeutLocal _ _ _ ->
606+ NeutLocal _ _ ->
597607 go binding
598608 NeutStop _ ->
599609 go binding
@@ -604,33 +614,38 @@ makeLet ident binding go = case binding of
604614
605615deref :: BackendSemantics -> BackendSemantics
606616deref = case _ of
607− NeutLocal _ _ (Just expr) -> expr
608− expr -> expr
617+ SemRef _ _ sem ->
618+ force sem
619+ sem ->
620+ sem
609621
610−-- TODO: Check for overflow in Int ops since backends may not handle it the
611−-- same was as the JS backend.
612622evalPrimOp :: Env -> BackendOperator BackendSemantics -> BackendSemantics
613623evalPrimOp env = case _ of
614624 Op1 op1 x ->
615625 case op1, x of
616− OpBooleanNot, NeutLit (LitBoolean bool) ->
617− liftBoolean (not bool)
618− OpBooleanNot, NeutPrimOp op ->
619− evalPrimOpNot op
620− OpIntBitNot, NeutLit (LitInt a) ->
621− liftInt (complement a)
626+ OpBooleanNot, _
627+ | NeutLit (LitBoolean bool) <- deref x ->
628+ liftBoolean (not bool)
629+ OpBooleanNot, _
630+ | NeutPrimOp op <- deref x ->
631+ evalPrimOpNot op
632+ OpIntBitNot, _
633+ | NeutLit (LitInt a) <- deref x ->
634+ liftInt (complement a)
622635 OpIsTag a, _
623636 | NeutData b _ _ _ _ <- deref x ->
624637 liftBoolean (a == b)
625638 OpArrayLength, _
626639 | NeutLit (LitArray arr) <- deref x ->
627640 liftInt (Array.length arr)
628− OpIntNegate, NeutLit (LitInt a) ->
629− liftInt (negate a)
630− OpNumberNegate, NeutLit (LitNumber a) ->
631− liftNumber (negate a)
632− _, SemExtern qual spine _ ->
633− evalExtern env qual $ Array.snoc spine (ExternPrimOp op1)
641+ OpIntNegate, _
642+ | NeutLit (LitInt a) <- deref x ->
643+ liftInt (negate a)
644+ OpNumberNegate, _
645+ | NeutLit (LitNumber a) <- deref x ->
646+ liftNumber (negate a)
647+ _, SemRef ref spine sem ->
648+ evalRef env ref spine (ExternPrimOp op1) sem
634649 _, NeutFail err ->
635650 NeutFail err
636651 _, _ ->
@@ -639,83 +654,83 @@ evalPrimOp env = case _ of
639654 Op2 op2 x y ->
640655 case op2 of
641656 OpBooleanAnd
642− | NeutLit (LitBoolean false) <- x ->
657+ | NeutLit (LitBoolean false) <- deref x ->
643658 x
644− | NeutLit (LitBoolean false) <- y ->
659+ | NeutLit (LitBoolean false) <- deref y ->
645660 y
646− | NeutLit (LitBoolean true) <- x ->
661+ | NeutLit (LitBoolean true) <- deref x ->
647662 y
648− | NeutLit (LitBoolean true) <- y ->
663+ | NeutLit (LitBoolean true) <- deref y ->
649664 x
650665 OpBooleanOr
651− | NeutLit (LitBoolean false) <- x ->
666+ | NeutLit (LitBoolean false) <- deref x ->
652667 y
653− | NeutLit (LitBoolean false) <- y ->
668+ | NeutLit (LitBoolean false) <- deref y ->
654669 x
655− | NeutLit (LitBoolean true) <- x ->
670+ | NeutLit (LitBoolean true) <- deref x ->
656671 x
657− | NeutLit (LitBoolean true) <- y ->
672+ | NeutLit (LitBoolean true) <- deref y ->
658673 y
659674 OpBooleanOrd OpEq
660− | NeutLit (LitBoolean bool) <- x ->
675+ | NeutLit (LitBoolean bool) <- deref x ->
661676 if bool then y else evalPrimOp env (Op1 OpBooleanNot y)
662− | NeutLit (LitBoolean bool) <- y ->
677+ | NeutLit (LitBoolean bool) <- deref y ->
663678 if bool then x else evalPrimOp env (Op1 OpBooleanNot x)
664679 OpBooleanOrd op
665− | NeutLit (LitBoolean a) <- x
666− , NeutLit (LitBoolean b) <- y ->
680+ | NeutLit (LitBoolean a) <- deref x
681+ , NeutLit (LitBoolean b) <- deref y ->
667682 liftBoolean (evalPrimOpOrd op a b)
668683 OpCharOrd op
669− | NeutLit (LitChar a) <- x
670− , NeutLit (LitChar b) <- y ->
684+ | NeutLit (LitChar a) <- deref x
685+ , NeutLit (LitChar b) <- deref y ->
671686 liftBoolean (evalPrimOpOrd op a b)
672687 OpIntBitAnd
673− | NeutLit (LitInt a) <- x
674− , NeutLit (LitInt b) <- y ->
688+ | NeutLit (LitInt a) <- deref x
689+ , NeutLit (LitInt b) <- deref y ->
675690 liftInt (a .&. b)
676691 OpIntBitOr
677− | NeutLit (LitInt a) <- x
678− , NeutLit (LitInt b) <- y ->
692+ | NeutLit (LitInt a) <- deref x
693+ , NeutLit (LitInt b) <- deref y ->
679694 liftInt (a .|. b)
680695 OpIntBitShiftLeft
681− | NeutLit (LitInt a) <- x
682− , NeutLit (LitInt b) <- y ->
696+ | NeutLit (LitInt a) <- deref x
697+ , NeutLit (LitInt b) <- deref y ->
683698 liftInt (shl a b)
684699 OpIntBitShiftRight
685− | NeutLit (LitInt a) <- x
686− , NeutLit (LitInt b) <- y ->
700+ | NeutLit (LitInt a) <- deref x
701+ , NeutLit (LitInt b) <- deref y ->
687702 liftInt (shr a b)
688703 OpIntBitXor
689− | NeutLit (LitInt a) <- x
690− , NeutLit (LitInt b) <- y ->
704+ | NeutLit (LitInt a) <- deref x
705+ , NeutLit (LitInt b) <- deref y ->
691706 liftInt (xor a b)
692707 OpIntBitZeroFillShiftRight
693− | NeutLit (LitInt a) <- x
694− , NeutLit (LitInt b) <- y ->
708+ | NeutLit (LitInt a) <- deref x
709+ , NeutLit (LitInt b) <- deref y ->
695710 liftInt (zshr a b)
696711 OpIntNum OpSubtract
697− | NeutLit (LitInt 0) <- x ->
712+ | NeutLit (LitInt 0) <- deref x ->
698713 evalPrimOp env (Op1 OpIntNegate y)
699714 OpIntNum op
700715 | Just result <- evalPrimOpNumInt op x y ->
701716 result
702717 OpIntOrd op
703− | NeutLit (LitInt a) <- x
704− , NeutLit (LitInt b) <- y ->
718+ | NeutLit (LitInt a) <- deref x
719+ , NeutLit (LitInt b) <- deref y ->
705720 liftBoolean (evalPrimOpOrd op a b)
706721 OpNumberNum OpSubtract
707− | NeutLit (LitNumber 0.0) <- x ->
722+ | NeutLit (LitNumber 0.0) <- deref x ->
708723 evalPrimOp env (Op1 OpNumberNegate y)
709724 OpNumberNum op
710725 | Just result <- evalPrimOpNumNumber op x y ->
711726 result
712727 OpNumberOrd op
713− | NeutLit (LitNumber a) <- x
714− , NeutLit (LitNumber b) <- y ->
728+ | NeutLit (LitNumber a) <- deref x
729+ , NeutLit (LitNumber b) <- deref y ->
715730 liftBoolean (evalPrimOpOrdNumber op a b)
716731 OpStringOrd op
717− | NeutLit (LitString a) <- x
718− , NeutLit (LitString b) <- y ->
732+ | NeutLit (LitString a) <- deref x
733+ , NeutLit (LitString b) <- deref y ->
719734 liftBoolean (evalPrimOpOrd op a b)
720735 OpStringAppend
721736 | Just result <- evalPrimOpAssocL OpStringAppend caseString (\a b -> Just $ liftString (a <> b)) x y ->
@@ -802,16 +817,16 @@ evalPrimOpOrdNumber op x y = case op of
802817evalPrimOpNumNumber :: BackendOperatorNum -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
803818evalPrimOpNumNumber op x y = case op of
804819 OpAdd ->
805− evalPrimOpAssocL (OpNumberNum OpAdd) caseNumber (\a b -> Just $ liftNumber (a + b)) x y
820+ evalPrimOpAssocL (OpNumberNum OpAdd) (caseNumber <<< deref) (\a b -> Just $ liftNumber (a + b)) x y
806821 OpMultiply ->
807− evalPrimOpAssocL (OpNumberNum OpMultiply) caseNumber (\a b -> Just $ liftNumber (a * b)) x y
822+ evalPrimOpAssocL (OpNumberNum OpMultiply) (caseNumber <<< deref) (\a b -> Just $ liftNumber (a * b)) x y
808823 OpSubtract
809− | NeutLit (LitNumber a) <- x
810− , NeutLit (LitNumber b) <- y ->
824+ | NeutLit (LitNumber a) <- deref x
825+ , NeutLit (LitNumber b) <- deref y ->
811826 Just $ liftNumber (a - b)
812827 OpDivide
813− | NeutLit (LitNumber a) <- x
814− , NeutLit (LitNumber b) <- y ->
828+ | NeutLit (LitNumber a) <- deref x
829+ , NeutLit (LitNumber b) <- deref y ->
815830 Just $ liftNumber (a / b)
816831 _ ->
817832 Nothing
@@ -819,7 +834,7 @@ evalPrimOpNumNumber op x y = case op of
819834evalPrimOpNumInt :: BackendOperatorNum -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
820835evalPrimOpNumInt op x y = case op of
821836 OpAdd ->
822− evalPrimOpAssocL (OpIntNum OpAdd) caseInt addOverflow x y
837+ evalPrimOpAssocL (OpIntNum OpAdd) (caseInt <<< deref) addOverflow x y
823838 where
824839 addOverflow a b = do
825840 let res = a + b
@@ -828,7 +843,7 @@ evalPrimOpNumInt op x y = case op of
828843 else
829844 Just $ liftInt res
830845 OpMultiply ->
831− evalPrimOpAssocL (OpIntNum OpMultiply) caseInt mulOverflow x y
846+ evalPrimOpAssocL (OpIntNum OpMultiply) (caseInt <<< deref) mulOverflow x y
832847 where
833848 mulOverflow a b = do
834849 let res = a * b
@@ -837,16 +852,16 @@ evalPrimOpNumInt op x y = case op of
837852 else
838853 Just $ liftInt res
839854 OpSubtract
840− | NeutLit (LitInt a) <- x
841− , NeutLit (LitInt b) <- y -> do
855+ | NeutLit (LitInt a) <- deref x
856+ , NeutLit (LitInt b) <- deref y -> do
842857 let res = a - b
843858 if b > 0 && res > a || b < 0 && res < a then
844859 Nothing
845860 else
846861 Just $ liftInt res
847862 OpDivide
848− | NeutLit (LitInt a) <- x
849− , NeutLit (LitInt b) <- y ->
863+ | NeutLit (LitInt a) <- deref x
864+ , NeutLit (LitInt b) <- deref y ->
850865 Just $ liftInt (a / b)
851866 _ ->
852867 Nothing
@@ -883,10 +898,41 @@ primOpOrdNot = case _ of
883898 OpGt -> OpLte
884899 OpGte -> OpLt
885900
886−evalExtern :: Env -> Qualified Ident -> Array ExternSpine -> BackendSemantics
887−evalExtern env@(Env e) qual spine = case e.evalExtern env qual spine of
888− Nothing -> SemExtern qual spine (defer \_ -> neutralSpine (NeutVar qual) spine)
889− Just sem -> sem
901+evalRef :: Env -> EvalRef -> Array ExternSpine -> ExternSpine -> Lazy BackendSemantics -> BackendSemantics
902+evalRef env@(Env e) ref spine last sem = case ref of
903+ EvalExtern qual
904+ | Just sem' <- e.evalExternSpine env qual spine' ->
905+ sem'
906+ _ ->
907+ SemRef ref spine' $ defer \_ ->
908+ deref $ evalRefSpine env ref spine' sem last
909+ where
910+ spine' = snocSpine spine last
911+
912+evalRefSpine :: Env -> EvalRef -> Array ExternSpine -> Lazy BackendSemantics -> ExternSpine -> BackendSemantics
913+evalRefSpine env ref spine sem = case _ of
914+ ExternApp _ ->
915+ neutralSpine (evalEvalRef ref) spine
916+ ExternUncurriedApp _ ->
917+ neutralSpine (evalEvalRef ref) spine
918+ ExternAccessor acc ->
919+ evalAccessor env (force sem) acc
920+ ExternPrimOp op ->
921+ evalPrimOp env (Op1 op (force sem))
922+
923+evalEvalRef :: EvalRef -> BackendSemantics
924+evalEvalRef = case _ of
925+ EvalExtern qual ->
926+ NeutVar qual
927+ EvalLocal ident lvl ->
928+ NeutLocal ident lvl
929+
930+snocSpine :: Array ExternSpine -> ExternSpine -> Array ExternSpine
931+snocSpine spine = case _ of
932+ ExternApp apps ->
933+ foldl snocApp spine apps
934+ other ->
935+ Array.snoc spine other
890936
891937envForGroup :: Env -> EvalRef -> InlineAccessor -> Array (Qualified Ident) -> Env
892938envForGroup env ref acc group
@@ -1031,6 +1077,30 @@ evalExternFromImpl env@(Env e) qual (Tuple analysis impl) spine = case spine of
10311077 _ ->
10321078 Nothing
10331079
1080+evalExternRefFromImpl :: Env -> Qualified Ident -> Tuple BackendAnalysis ExternImpl -> BackendSemantics
1081+evalExternRefFromImpl env qual (Tuple _ impl) = case impl of
1082+ ExternExpr group (NeutralExpr expr)
1083+ | isRefExpr expr ->
1084+ eval (envForGroup env (EvalExtern qual) InlineRef group) expr
1085+ ExternDict group props ->
1086+ NeutLit $ LitRecord $ map
1087+ ( \(Prop prop (Tuple _ (NeutralExpr expr))) ->
1088+ Prop prop $ eval (envForGroup env (EvalExtern qual) (InlineProp prop) group) expr
1089+ )
1090+ props
1091+ _ ->
1092+ NeutVar qual
1093+
1094+isRefExpr :: forall a. BackendSyntax a -> Boolean
1095+isRefExpr = case _ of
1096+ Var _ -> true
1097+ Lit _ -> true
1098+ CtorSaturated _ _ _ _ _ -> true
1099+ Accessor _ _ -> true
1100+ Update _ _ -> true
1101+ PrimOp _ -> true
1102+ _ -> false
1103+
10341104analysisFromDirective :: BackendAnalysis -> InlineDirective -> BackendAnalysis
10351105analysisFromDirective (BackendAnalysis analysis) = case _ of
10361106 InlineAlways ->
@@ -1091,21 +1161,21 @@ quote = go
10911161 -- Block constructors
10921162 SemLet ident binding k -> do
10931163 let Tuple level ctx' = nextLevel ctx
1094− build ctx $ Let ident level (quote (ctx { effect = false }) binding) $ quote ctx' $ k $ NeutLocal ident level (Just binding)
1164+ build ctx $ Let ident level (quote (ctx { effect = false }) binding) $ quote ctx' $ k $ SemRef (EvalLocal ident level) [] $ defer \_ -> deref binding
10951165 SemLetRec bindings k -> do
10961166 let Tuple level ctx' = nextLevel ctx
10971167 -- We are not currently propagating references
10981168 -- to recursive bindings. The language requires
10991169 -- a runtime check for strictly recursive bindings
11001170 -- which we don't currently implement.
1101− let neutBindings = (\(Tuple ident _) -> Tuple ident $ defer \_ -> NeutLocal (Just ident) level Nothing) <$> bindings
1171+ let neutBindings = (\(Tuple ident _) -> Tuple ident $ defer \_ -> NeutLocal (Just ident) level) <$> bindings
11021172 build ctx $ LetRec level
11031173 (map (\b -> quote (ctx' { effect = false }) $ b neutBindings) <$> bindings)
11041174 (quote ctx' $ k neutBindings)
11051175 SemEffectBind ident binding k -> do
11061176 let ctx' = ctx { effect = true }
11071177 let Tuple level ctx'' = nextLevel ctx'
1108− build ctx $ EffectBind ident level (quote ctx' binding) $ quote ctx'' $ k $ NeutLocal ident level (Just binding)
1178+ build ctx $ EffectBind ident level (quote ctx' binding) $ quote ctx'' $ k $ NeutLocal ident level
11091179 SemEffectPure sem ->
11101180 build ctx $ EffectPure (quote (ctx { effect = false }) sem)
11111181 SemEffectDefer sem ->
@@ -1117,17 +1187,21 @@ quote = go
11171187 foldr (buildBranchCond ctx) (quote ctx <<< force $ def) branches'
11181188
11191189 -- Non-block constructors
1120− SemExtern _ _ sem ->
1121− go ctx (force sem)
1190+ SemRef ref sp _ ->
1191+ case ref of
1192+ EvalExtern qual ->
1193+ go ctx $ neutralSpine (NeutVar qual) sp
1194+ EvalLocal ident lvl ->
1195+ go ctx $ neutralSpine (NeutLocal ident lvl) sp
11221196 SemLam ident k -> do
11231197 let Tuple level ctx' = nextLevel ctx
1124− build ctx $ Abs (NonEmptyArray.singleton (Tuple ident level)) $ quote (ctx' { effect = false }) $ k $ NeutLocal ident level Nothing
1198+ build ctx $ Abs (NonEmptyArray.singleton (Tuple ident level)) $ quote (ctx' { effect = false }) $ k $ NeutLocal ident level
11251199 SemMkFn pro -> do
11261200 let
11271201 loop ctx' idents = case _ of
11281202 MkFnNext ident k -> do
11291203 let Tuple lvl ctx'' = nextLevel ctx'
1130− loop ctx'' (Array.snoc idents (Tuple ident lvl)) (k (NeutLocal ident lvl Nothing))
1204+ loop ctx'' (Array.snoc idents (Tuple ident lvl)) (k (NeutLocal ident lvl))
11311205 MkFnApplied body ->
11321206 build ctx' $ UncurriedAbs idents $ quote (ctx' { effect = false }) body
11331207 loop ctx [] pro
@@ -1136,11 +1210,11 @@ quote = go
11361210 loop ctx' idents = case _ of
11371211 MkFnNext ident k -> do
11381212 let Tuple lvl ctx'' = nextLevel ctx'
1139− loop ctx'' (Array.snoc idents (Tuple ident lvl)) (k (NeutLocal ident lvl Nothing))
1213+ loop ctx'' (Array.snoc idents (Tuple ident lvl)) (k (NeutLocal ident lvl))
11401214 MkFnApplied body ->
11411215 build ctx' $ UncurriedEffectAbs idents $ quote (ctx' { effect = false }) body
11421216 loop ctx [] pro
1143− NeutLocal ident level _ ->
1217+ NeutLocal ident level ->
11441218 build ctx $ Local ident level
11451219 NeutVar qual ->
11461220 build ctx $ Var qual