public override IPStmt VisitInsertStmt(PParser.InsertStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr index = exprVisitor.Visit(context.expr()); IPExpr value = exprVisitor.Visit(context.rvalue()); // Check linear types var valueIsInvariant = false; if (value is ILinearRef linearRef) { valueIsInvariant = linearRef.LinearType.Equals(LinearType.Swap); } // Check subtyping PLanguageType keyType = index.Type; PLanguageType valueType = value.Type; PLanguageType expectedKeyType; PLanguageType expectedValueType; switch (variable.Type.Canonicalize()) { case SequenceType sequenceType: expectedKeyType = PrimitiveType.Int; expectedValueType = sequenceType.ElementType; break; case MapType mapType: expectedKeyType = mapType.KeyType; expectedValueType = mapType.ValueType; break; default: throw handler.TypeMismatch(variable, TypeKind.Sequence, TypeKind.Map); } if (!expectedKeyType.IsAssignableFrom(keyType)) { throw handler.TypeMismatch(context.rvalue(), keyType, expectedKeyType); } if (valueIsInvariant && !expectedValueType.IsSameTypeAs(valueType) || !valueIsInvariant && !expectedValueType.IsAssignableFrom(valueType)) { throw handler.TypeMismatch(context.rvalue(), valueType, expectedValueType); } return(new InsertStmt(context, variable, index, value)); }