@@ -386,8 +386,9 @@ object ViperChopper {
386
386
case Vertex .Always => 0
387
387
}
388
388
389
- override def mergePenalty (lhsExclusivePrice : Int , rhsExclusivePrice : Int , sharedPrice : Int ): Int =
389
+ override def mergePenalty (lhsExclusivePrice : Int , rhsExclusivePrice : Int , sharedPrice : Int ): Int = {
390
390
(lhsExclusivePrice + rhsExclusivePrice) * ((conf.sharedThreshold + sharedPrice).toFloat / conf.sharedThreshold).toInt
391
+ }
391
392
}
392
393
393
394
object Default extends DefaultImpl (defaultPenaltyConfig)
@@ -437,7 +438,7 @@ object ViperChopper {
437
438
}
438
439
// The isotated nodes are always and all selected nodes
439
440
val alwaysId = id(Always )
440
- val isolatedNodes = alwaysId +: members.filter(selector).map(m => id(Vertex .toVertex (m)))
441
+ val isolatedNodes = alwaysId +: members.filter(selector).map(m => id(Vertex .toDefVertex (m)))
441
442
442
443
val vertices = Array .ofDim[Vertex ](N )
443
444
for ((vertex, idx) <- vertexToId) { vertices(idx) = vertex }
@@ -457,22 +458,49 @@ object ViperChopper {
457
458
/** Abstract the smallest parts of a Viper program and provides necessary information to compute merge penalties. */
458
459
sealed trait Vertex
459
460
object Vertex {
460
- case class Method (methodName : String ) extends Vertex
461
+ case class Method private [ Vertex ] (methodName : String ) extends Vertex
461
462
case class MethodSpec (methodName : String ) extends Vertex
462
463
case class Function (functionName : String ) extends Vertex
463
464
case class PredicateSig (predicateName : String ) extends Vertex
464
- case class PredicateBody (predicateName : String ) extends Vertex
465
+ case class PredicateBody private [ Vertex ] (predicateName : String ) extends Vertex
465
466
case class Field (fieldName : String ) extends Vertex
466
467
case class DomainFunction (funcName : String ) extends Vertex
467
468
case class DomainAxiom (v : vpr.DomainAxiom , d : vpr.Domain ) extends Vertex
468
469
case class DomainType (v : vpr.DomainType ) extends Vertex
469
470
case object Always extends Vertex // if something always has to be included, then it is a dependency of Always
470
471
471
- def toVertex (m : vpr.Member ): Vertex = {
472
+ // the creation of the following vertices has special cases and should not happen outside of the Vertex object
473
+ object Method { private [Vertex ] def apply (methodName : String ): Method = new Method (methodName) }
474
+ object PredicateBody { private [Vertex ] def apply (predicateName : String ): PredicateBody = new PredicateBody (predicateName) }
475
+ /** This function is only allowed to be called in the following cases:
476
+ * 1) applying [[toDefVertex ]] to the predicate referenced by `predicateName` returns a [[Vertex.PredicateBody ]] instance.
477
+ * 2) The result is used as the target of a dependency.
478
+ * */
479
+ def predicateBody_check_that_call_is_ok (predicateName : String ): PredicateBody = Vertex .PredicateBody (predicateName)
480
+
481
+ def toDefVertex (m : vpr.Member ): Vertex = {
482
+
483
+ m match {
484
+ case m : vpr.Method => m.body match {
485
+ case Some (_) => Vertex .Method (m.name)
486
+ case None => Vertex .MethodSpec (m.name)
487
+ }
488
+ case m : vpr.Predicate => m.body match {
489
+ case Some (_) => Vertex .PredicateBody (m.name)
490
+ case None => Vertex .PredicateSig (m.name)
491
+ }
492
+ case m : vpr.Function => Vertex .Function (m.name)
493
+ case m : vpr.Field => Vertex .Field (m.name)
494
+ case m : vpr.Domain => Vertex .DomainType (vpr.DomainType (domain = m, (m.typVars zip m.typVars).toMap))
495
+ case _ : vpr.ExtensionMember => ???
496
+ }
497
+ }
498
+
499
+ def toUseVertex (m : vpr.Member ): Vertex = {
472
500
m match {
473
- case m : vpr.Method => Vertex .Method (m.name)
501
+ case m : vpr.Method => Vertex .MethodSpec (m.name)
474
502
case m : vpr.Function => Vertex .Function (m.name)
475
- case m : vpr.Predicate => Vertex .PredicateBody (m.name)
503
+ case m : vpr.Predicate => Vertex .PredicateSig (m.name)
476
504
case m : vpr.Field => Vertex .Field (m.name)
477
505
case m : vpr.Domain => Vertex .DomainType (vpr.DomainType (domain = m, (m.typVars zip m.typVars).toMap))
478
506
case _ : vpr.ExtensionMember => ???
@@ -535,33 +563,20 @@ object ViperChopper {
535
563
* The edges are sorted at a later point, after the translation to int nodes (where it is cheaper).
536
564
* */
537
565
def dependencies (member : vpr.Member ): Seq [Edge [Vertex ]] = {
566
+ val defVertex = Vertex .toDefVertex(member)
567
+ val useVertex = Vertex .toUseVertex(member)
568
+
538
569
member match {
539
570
case m : vpr.Method =>
540
- {
541
- val from = Vertex .Method (m.name)
542
- usages(m).map(from -> _)
543
- } ++ {
544
- val from = Vertex .MethodSpec (m.name)
545
- (m.pres ++ m.posts ++ m.formalArgs ++ m.formalReturns).flatMap(exp => usages(exp).map(from -> _))
546
- }
547
-
548
- case f : vpr.Function =>
549
- val from = Vertex .Function (f.name)
550
- usages(f).map(from -> _)
571
+ dependenciesToChildren(member, defVertex) ++
572
+ (m.pres ++ m.posts ++ m.formalArgs ++ m.formalReturns).flatMap(dependenciesToChildren(_, useVertex))
551
573
552
574
case p : vpr.Predicate =>
553
- {
554
- val from = Vertex .PredicateSig (p.name)
555
- p.formalArgs.flatMap(exp => usages(exp).map(from -> _))
556
- } ++ {
557
- val from = Vertex .PredicateBody (p.name)
558
- usages(p).map(from -> _)
559
- } ++ { Seq (Vertex .PredicateBody (p.name) -> Vertex .PredicateSig (p.name)) }
560
-
575
+ dependenciesToChildren(member, defVertex) ++
576
+ p.formalArgs.flatMap(dependenciesToChildren(_, useVertex)) ++
577
+ Seq (defVertex -> useVertex)
561
578
562
- case f : vpr.Field =>
563
- val from = Vertex .Field (f.name)
564
- usages(f).map(from -> _)
579
+ case _ : vpr.Function | _ : vpr.Field => dependenciesToChildren(member, defVertex)
565
580
566
581
case d : vpr.Domain =>
567
582
d.axioms.flatMap { ax =>
@@ -573,21 +588,24 @@ object ViperChopper {
573
588
* as a conservative choice. We use that dependencies of `Always` are always included.
574
589
*/
575
590
val mid = Vertex .DomainAxiom (ax, d)
576
- val tos = usages(ax.exp)
591
+ val tos = usages(ax.exp) // `tos` can be used as source because axioms do not contain un-/foldings.
577
592
val froms = tos
578
593
val finalFroms = if (froms.nonEmpty) froms else Vector (Vertex .Always )
579
594
finalFroms.map(_ -> mid) ++ tos.map(mid -> _)
580
- } ++ d.functions.flatMap { f =>
581
- val from = Vertex .DomainFunction (f.name)
582
- usages(f).map(from -> _)
583
- }
595
+ } ++ d.functions.flatMap { f => dependenciesToChildren(f, Vertex .DomainFunction (f.name)) }
584
596
585
597
case _ => Vector .empty
586
598
}
587
599
}
588
600
601
+ /** Returns edges from `nodeVertex` to all children of `node` that are usages. */
602
+ def dependenciesToChildren (node : vpr.Node , nodeVertex : Vertex ): Seq [Edge [Vertex ]] = {
603
+ usages(node) map (nodeVertex -> _)
604
+ }
605
+
589
606
/**
590
607
* Returns all entities referenced in the subtree of node `n`.
608
+ * May only be used as the target of a dependency.
591
609
* The result is an unsorted sequence of vertices.
592
610
* The vertices are never sorted, and duplicates are fine.
593
611
* Note that they are sorted indirectly when the edges are sorted.
@@ -604,9 +622,10 @@ object ViperChopper {
604
622
case n : vpr.FuncApp => Seq (Vertex .Function (n.funcname))
605
623
case n : vpr.DomainFuncApp => Seq (Vertex .DomainFunction (n.funcname))
606
624
case n : vpr.PredicateAccess => Seq (Vertex .PredicateSig (n.predicateName))
607
- case n : vpr.Unfold => Seq (Vertex .PredicateBody (n.acc.loc.predicateName))
608
- case n : vpr.Fold => Seq (Vertex .PredicateBody (n.acc.loc.predicateName))
609
- case n : vpr.Unfolding => Seq (Vertex .PredicateBody (n.acc.loc.predicateName))
625
+ // The call is fine because the result is used as the target of a dependency.
626
+ case n : vpr.Unfold => Seq (Vertex .predicateBody_check_that_call_is_ok(n.acc.loc.predicateName))
627
+ case n : vpr.Fold => Seq (Vertex .predicateBody_check_that_call_is_ok(n.acc.loc.predicateName))
628
+ case n : vpr.Unfolding => Seq (Vertex .predicateBody_check_that_call_is_ok(n.acc.loc.predicateName))
610
629
case n : vpr.FieldAccess => Seq (Vertex .Field (n.field.name))
611
630
case n : vpr.Type => deepType(n).collect{ case t : vpr.DomainType => Vertex .DomainType (t) }
612
631
}.flatten
0 commit comments