77package viper .silver .parser
88
99import java .util .concurrent .atomic .{AtomicInteger , AtomicLong }
10-
1110import viper .silver .ast .utility .Visitor
1211import viper .silver .ast .utility .rewriter .{Rewritable , StrategyBuilder }
1312import viper .silver .ast .{Exp , MagicWandOp , Member , NoPosition , Position , Stmt , Type }
@@ -243,6 +242,8 @@ case class PDomainType(domain: PIdnUse, args: Seq[PType])(val pos: (Position, Po
243242 r
244243 }
245244
245+ override def withTypeArguments (s : Seq [PType ]) = copy(args = s)(pos)
246+
246247 override def toString = domain.name + (if (args.isEmpty) " " else s " [ ${args.mkString(" , " )}] " )
247248}
248249
@@ -292,6 +293,8 @@ trait PGenericType extends PType {
292293 def typeArguments : Seq [PType ]
293294 override def isGround = typeArguments.forall(_.isGround)
294295 override def toString = s " $genericName[ ${typeArguments.mkString(" , " )}] "
296+
297+ def withTypeArguments (s : Seq [PType ]) : PGenericType
295298}
296299
297300sealed trait PGenericCollectionType extends PGenericType {
@@ -304,14 +307,20 @@ sealed trait PGenericCollectionType extends PGenericType {
304307case class PSeqType (elementType : PType )(val pos : (Position , Position ) = (NoPosition , NoPosition )) extends PType with PGenericCollectionType {
305308 override val genericName = " Seq"
306309 override def substitute (map : PTypeSubstitution ) = PSeqType (elementType.substitute(map))(pos)
310+
311+ override def withTypeArguments (s : Seq [PType ]) = copy(elementType = s.head)(pos)
307312}
308313case class PSetType (elementType : PType )(val pos : (Position , Position ) = (NoPosition , NoPosition )) extends PType with PGenericCollectionType {
309314 override val genericName = " Set"
310315 override def substitute (map : PTypeSubstitution ) = PSetType (elementType.substitute(map))(pos)
316+
317+ override def withTypeArguments (s : Seq [PType ]) = copy(elementType = s.head)(pos)
311318}
312319case class PMultisetType (elementType : PType )(val pos : (Position , Position ) = (NoPosition , NoPosition )) extends PType with PGenericCollectionType {
313320 override val genericName = " Multiset"
314321 override def substitute (map : PTypeSubstitution ) = PMultisetType (elementType.substitute(map))(pos)
322+
323+ override def withTypeArguments (s : Seq [PType ]): PMultisetType = copy(elementType = s.head)(pos)
315324}
316325
317326case class PMapType (keyType : PType , valueType : PType )(val pos : (Position , Position ) = (NoPosition , NoPosition )) extends PType with PGenericType {
@@ -321,6 +330,8 @@ case class PMapType(keyType : PType, valueType : PType)(val pos: (Position, Posi
321330
322331 override def isValidOrUndeclared = typeArguments.forall(_.isValidOrUndeclared)
323332 override def substitute (map : PTypeSubstitution ) = PMapType (keyType.substitute(map), valueType.substitute(map))(pos)
333+
334+ override def withTypeArguments (s : Seq [PType ]): PMapType = copy(keyType = s.head, valueType = s(1 ))(pos)
324335}
325336
326337/** Type used for internal nodes (e.g. typing predicate accesses) - should not be
@@ -382,27 +393,42 @@ class PTypeSubstitution(val m:Map[String,PType]) //extends Map[String,PType]()
382393 val ts = PTypeSubstitution (Map (a -> b))
383394 PTypeSubstitution (m.map(kv => kv._1 -> kv._2.substitute(ts)))
384395 }
385- def * (other: PTypeSubstitution ) : Option [PTypeSubstitution ] =
386- other.m.foldLeft(Some (this ): Option [PTypeSubstitution ])({
387- case (Some (s),p)=> s.add(PTypeVar (p._1),p._2);
388- case (None ,_) => None })
389396
390- def add (a: String ,b: PType ): Option [PTypeSubstitution ] = add(PTypeVar (a),b)
397+ // The following methods all return a type substitution if successful,
398+ // otherwise a pair containing the expected and the found type.
399+ def * (other: PTypeSubstitution ) : Either [(PType , PType ), PTypeSubstitution ] =
400+ other.m.foldLeft(Right (this ): Either [(PType , PType ), PTypeSubstitution ])({
401+ case (Right (s),p)=> s.add(PTypeVar (p._1),p._2);
402+ case (l@ Left (_),_) => l })
403+
404+ def add (a: String ,b: PType ): Either [(PType , PType ), PTypeSubstitution ] = add(PTypeVar (a),b)
391405
392- def add (a: PType ,b: PType ): Option [ PTypeSubstitution ] = {
406+ def add (a: PType ,b: PType ): Either [( PType , PType ), PTypeSubstitution ] = {
393407 val as = a.substitute(this )
394408 val bs = b.substitute(this )
395409 (as, bs) match {
396- case (aa,bb) if aa == bb => Some (this )
397- case (PTypeVar (name), t) if PTypeVar .isFreePTVName(name) => assert(! contains(name)); Some (substitute(name,t)+ (name-> t))
410+ case (aa,bb) if aa == bb => Right (this )
411+ case (PTypeVar (name), t) if PTypeVar .isFreePTVName(name) => assert(! contains(name)); Right (substitute(name,t)+ (name-> t))
398412 case (_, PTypeVar (name)) if PTypeVar .isFreePTVName(name) => add(bs,as)
399413 case (gt1 : PGenericType , gt2 : PGenericType ) if gt1.genericName == gt2.genericName =>
400- ((gt1.typeArguments zip gt2.typeArguments).foldLeft[Option [PTypeSubstitution ]](Some (this ))
401- ((ss : Option [PTypeSubstitution ], p : (PType , PType )) => ss match {
402- case Some (sss) => sss.add(p._1,p._2)
403- case None => None
414+ val zippedArgs = gt1.typeArguments zip gt2.typeArguments
415+ (zippedArgs.foldLeft[Either [(PType , PType ), PTypeSubstitution ]](Right (this ))
416+ ((ss : Either [(PType , PType ), PTypeSubstitution ], p : (PType , PType )) => ss match {
417+ case Right (sss) => sss.add(p._1,p._2) match {
418+ case l@ Left (pair) =>
419+ val problemArg = zippedArgs.zipWithIndex.find(_._1 == pair)
420+ problemArg match {
421+ case None => l
422+ case Some ((_, index)) =>
423+ val newArgs = zippedArgs.updated(index, pair)
424+ val (argsA, argsB) = newArgs.unzip
425+ Left (gt1.withTypeArguments(argsA), gt1.withTypeArguments(argsB))
426+ }
427+ case r => r
428+ }
429+ case Left ((aa, bb)) => Left ((aa, bb))
404430 }))
405- case _ => None
431+ case (aa, bb) => Left ((aa, bb))
406432 }
407433
408434 }
@@ -516,7 +542,7 @@ case class PCall(func: PIdnUse, args: Seq[PExp], typeAnnotated : Option[PType] =
516542 assert(s3.m.forall(_._2.isGround))
517543 domainSubstitution = Some (s3)
518544 dtr.mm.values.foldLeft(ots)(
519- (tss,s)=> if (tss.contains(s)) tss else tss.add(s, PTypeSubstitution .defaultType).get )
545+ (tss,s)=> if (tss.contains(s)) tss else tss.add(s, PTypeSubstitution .defaultType).getOrElse( null ) )
520546 case _ => ots
521547 }
522548 super .forceSubstitution(ts)
0 commit comments