@@ -243,7 +243,9 @@ private TranslatedValue translateOperatorCall(
243243 // by our axioms
244244 return TranslatedValue .propagateStrict (ctx , typeSystem , typeSystem .mkError (), args );
245245 case INDEX :
246- return translateIndex (args , ast );
246+ return translateIndex (args , ast , false );
247+ case OPTIONAL_INDEX :
248+ return translateIndex (args , ast , true );
247249 case CONDITIONAL :
248250 return translateConditional (args , ast );
249251 case NOT_STRICTLY_FALSE :
@@ -600,7 +602,7 @@ private TranslatedValue translateEquality(
600602 .withApproximation (ctx .mkFalse ());
601603 }
602604
603- private Expr <?> buildListIndex (Expr <?> lhsTrans , Expr <?> rhsTrans , BoolExpr typeGuard ) {
605+ private Expr <?> buildListIndex (Expr <?> lhsTrans , Expr <?> rhsTrans , BoolExpr typeGuard , boolean isOptional ) {
604606 Expr <?> listRef = typeSystem .getListRef (lhsTrans );
605607 SeqExpr <?> seq = typeSystem .getSeq (listRef );
606608 Expr <?> index = typeSystem .getInt (rhsTrans );
@@ -617,6 +619,13 @@ private Expr<?> buildListIndex(Expr<?> lhsTrans, Expr<?> rhsTrans, BoolExpr type
617619 constraintSink .accept (ctx .mkImplies (ctx .mkAnd (typeGuard , inBounds ), valNotUnknown ));
618620 }
619621
622+ if (isOptional ) {
623+ Expr <?> resultOptRef = ctx .mkApp (typeSystem .optionalOfRefFunc (), val );
624+ constraintSink .accept (ctx .mkEq (typeSystem .getOptionalValue (resultOptRef ), val ));
625+ constraintSink .accept (typeSystem .optHasValue (resultOptRef ));
626+ return ctx .mkITE (inBounds , typeSystem .mkOptionalOf (resultOptRef ), typeSystem .mkOptionalNone ());
627+ }
628+
620629 return ctx .mkITE (inBounds , val , typeSystem .mkError ());
621630 }
622631
@@ -677,7 +686,7 @@ private ProbeResult createProbeResult(
677686 return new ProbeResult (altInMap , altVal );
678687 }
679688
680- private Expr <?> buildMapIndex (Expr <?> lhsTrans , Expr <?> rhsTrans , BoolExpr typeGuard ) {
689+ private Expr <?> buildMapIndex (Expr <?> lhsTrans , Expr <?> rhsTrans , BoolExpr typeGuard , boolean isOptional ) {
681690 Expr <?> mapRef = typeSystem .getMapRef (lhsTrans );
682691 ArrayExpr mapValues = (ArrayExpr ) typeSystem .getMapValues (mapRef );
683692 ArrayExpr mapPresence = (ArrayExpr ) typeSystem .getMapPresence (mapRef );
@@ -780,10 +789,17 @@ private Expr<?> buildMapIndex(Expr<?> lhsTrans, Expr<?> rhsTrans, BoolExpr typeG
780789 constraintSink .accept (ctx .mkImplies (ctx .mkAnd (typeGuard , finalInMap ), valNotUnknown ));
781790 }
782791
792+ if (isOptional ) {
793+ Expr <?> resultOptRef = ctx .mkApp (typeSystem .optionalOfRefFunc (), finalVal );
794+ constraintSink .accept (ctx .mkEq (typeSystem .getOptionalValue (resultOptRef ), finalVal ));
795+ constraintSink .accept (typeSystem .optHasValue (resultOptRef ));
796+ return ctx .mkITE (finalInMap , typeSystem .mkOptionalOf (resultOptRef ), typeSystem .mkOptionalNone ());
797+ }
798+
783799 return ctx .mkITE (finalInMap , finalVal , typeSystem .mkError ());
784800 }
785801
786- private TranslatedValue translateIndex (List <TranslatedValue > args , CelAbstractSyntaxTree ast ) {
802+ private TranslatedValue translateIndex (List <TranslatedValue > args , CelAbstractSyntaxTree ast , boolean isOptional ) {
787803 Expr <?> lhsTrans = args .get (0 ).z3Expr ();
788804 Expr <?> rhsTrans = args .get (1 ).z3Expr ();
789805
@@ -794,13 +810,13 @@ private TranslatedValue translateIndex(List<TranslatedValue> args, CelAbstractSy
794810
795811 Expr <?> actualValue ;
796812 if (lhsType .kind () == CelKind .LIST && rhsType .kind () == CelKind .INT ) {
797- actualValue = buildListIndex (lhsTrans , rhsTrans , ctx .mkTrue ());
813+ actualValue = buildListIndex (lhsTrans , rhsTrans , ctx .mkTrue (), isOptional );
798814 constraintSink .accept (
799815 ctx .mkImplies (
800816 ctx .mkNot (typeSystem .isError (actualValue )),
801817 typeConstraintGenerator .apply (actualValue , ((ListType ) lhsType ).elemType ())));
802818 } else if (lhsType .kind () == CelKind .MAP ) {
803- actualValue = buildMapIndex (lhsTrans , rhsTrans , ctx .mkTrue ());
819+ actualValue = buildMapIndex (lhsTrans , rhsTrans , ctx .mkTrue (), isOptional );
804820 constraintSink .accept (
805821 ctx .mkImplies (
806822 ctx .mkNot (typeSystem .isError (actualValue )),
@@ -810,8 +826,8 @@ private TranslatedValue translateIndex(List<TranslatedValue> args, CelAbstractSy
810826 BoolExpr isMapGuard = typeSystem .isMap (lhsTrans );
811827 actualValue =
812828 CelZ3TypeSystem .SwitchBuilder .newBuilder (ctx )
813- .addCase (isListGuard , buildListIndex (lhsTrans , rhsTrans , isListGuard ))
814- .addCase (isMapGuard , buildMapIndex (lhsTrans , rhsTrans , isMapGuard ))
829+ .addCase (isListGuard , buildListIndex (lhsTrans , rhsTrans , isListGuard , isOptional ))
830+ .addCase (isMapGuard , buildMapIndex (lhsTrans , rhsTrans , isMapGuard , isOptional ))
815831 .build (typeSystem .mkError ());
816832 }
817833
0 commit comments