@@ -699,7 +699,7 @@ case class TypeChecker(names: NameAnalyser) {
699699 check(fd.typ)
700700 fd.formalArgs foreach (a => check(a.typ))
701701 }
702- if (pfa.isDescendant[PAxiom ] && pfn.pres.toSeq.exists(pre => pre.k.rs == Requires )) {
702+ if (pfa.isDescendant[PAlwaysWellDefined ] && pfn.pres.toSeq.exists(pre => pre.k.rs == Requires )) {
703703 // A domain axiom, which must always be well-defined, is calling a function that has at least
704704 // one real precondition (i.e., not just a requires clause or something similar that's
705705 // temporarily represented as a precondition), which means that the call may not always be
@@ -941,6 +941,13 @@ case class DeclarationMap(
941941 def keys = decls.keys
942942}
943943
944+ // Used by `PNameAnalyserCustom`
945+ trait NameAnalyserCtxt {
946+ def getMap (): DeclarationMap
947+ def pushScope (s : PScope ): Unit
948+ def popScope (): Unit
949+ }
950+
944951/**
945952 * Resolves identifiers to their declaration. The important traits that relate to this are:
946953 * - `PDeclaration` marks a declaration of an identifier.
@@ -960,6 +967,7 @@ case class DeclarationMap(
960967 * - `PGlobalUniqueDeclaration`: marks a declaration as unique within the program.
961968 *
962969 * - `PNameAnalyserOpaque` marks a scope as opaque (should not be traversed by the name analyser).
970+ * - `PNameAnalyserCustom` marks a node which implements custom logic for name analysis.
963971 */
964972case class NameAnalyser () {
965973
@@ -992,41 +1000,79 @@ case class NameAnalyser() {
9921000
9931001 private val namesInScope = mutable.Set .empty[String ]
9941002
995- def check (g : PNode , target : Option [PNode ], initialCurScope : PScope = null ): Unit = {
996- var curScope : PScope = initialCurScope
997- def getMap (): DeclarationMap = Option (curScope).map(_.scopeId).map(localDeclarationMaps.get(_).get).getOrElse(globalDeclarationMap)
998-
1003+ case class NameAnalyserCtxt (names : NameAnalyser ) extends viper.silver.parser.NameAnalyserCtxt {
1004+ var curScope : PScope = null
9991005 val scopeStack = mutable.Stack [PScope ]()
10001006 var opaque = 0
10011007
1008+ def getMap (): DeclarationMap = Option (curScope).map(_.scopeId).map(names.localDeclarationMaps.get(_).get).getOrElse(names.globalDeclarationMap)
1009+
1010+ def pushScope (s : PScope ): Unit = {
1011+ names.localDeclarationMaps.put(s.scopeId, DeclarationMap (isMember = s.isInstanceOf [PMember ]))
1012+ scopeStack.push(curScope)
1013+ curScope = s
1014+ }
1015+
1016+ def popScope (): Unit = {
1017+ val popMap = localDeclarationMaps.get(curScope.scopeId).get
1018+ val newScope = scopeStack.pop()
1019+ curScope = newScope
1020+
1021+ val clashing = getMap().merge(popMap)
1022+ clashing.foreach { case (clashing, unique) =>
1023+ messages ++= FastMessaging .message(clashing.idndef, s " duplicate identifier ` ${clashing.idndef.name}` at ${clashing.idndef.pos._1} and at ${unique.idndef.pos._1}" )
1024+ }
1025+ }
1026+
1027+ def finish (): Unit = {
1028+ // If we started from some inner scope, walk all the way back out to the whole program
1029+ // with a variation of nodeUpNameCollectorVisitor
1030+ while (curScope != null ) {
1031+ val popMap = localDeclarationMaps.get(curScope.scopeId).get
1032+ curScope.getAncestor[PScope ] match {
1033+ case Some (newScope) =>
1034+ curScope = newScope
1035+ case None =>
1036+ curScope = null
1037+ }
1038+ getMap().merge(popMap)
1039+ }
1040+ }
1041+ }
1042+
1043+ def check (g : PNode , target : Option [PNode ], initialCurScope : PScope = null ): Unit = {
1044+ val ctx : NameAnalyserCtxt = NameAnalyserCtxt (this )
1045+ ctx.curScope = initialCurScope
1046+
10021047 val nodeDownNameCollectorVisitor = new PartialFunction [PNode , Unit ] {
10031048 def apply (n : PNode ) = {
10041049 if (n == target.orNull)
1005- namesInScope ++= getMap().keys
1050+ namesInScope ++= ctx. getMap().keys
10061051 n match {
10071052 // Opaque
10081053 case _ : PNameAnalyserOpaque =>
1009- opaque += 1
1010- case _ if opaque > 0 =>
1054+ ctx.opaque += 1
1055+ case _ if ctx.opaque > 0 =>
1056+ // Custom
1057+ case c : PNameAnalyserCustom =>
1058+ c.nameDown(ctx)
10111059 // Regular
10121060 case d : PDeclaration =>
10131061 // Add to declaration map
1014- val localDecls = getMap()
1062+ val localDecls = ctx. getMap()
10151063 localDecls.newDecl(d)
10161064 val clashing = localDecls.checkUnique(d, true )
10171065 if (clashing.isDefined)
10181066 messages ++= FastMessaging .message(d.idndef, s " duplicate identifier ` ${d.idndef.name}` at ${d.idndef.pos._1} and at ${clashing.get.idndef.pos._1}" )
10191067 case i : PIdnUseName [_] if target.isEmpty =>
1020- getMap().newRef(i)
1068+ ctx. getMap().newRef(i)
10211069 case _ =>
10221070 }
10231071
10241072 n match {
1025- case _ if opaque > 0 =>
1026- case s : PScope =>
1027- localDeclarationMaps.put(s.scopeId, DeclarationMap (isMember = s.isInstanceOf [PMember ]))
1028- scopeStack.push(curScope)
1029- curScope = s
1073+ case _ if ctx.opaque > 0 =>
1074+ case _ : PNameAnalyserCustom =>
1075+ case s : PScope => ctx.pushScope(s)
10301076 case _ =>
10311077 }
10321078 }
@@ -1037,6 +1083,7 @@ case class NameAnalyser() {
10371083 case _ : PScope => true
10381084 case _ : PIdnUseName [_] => true
10391085 case _ : PNameAnalyserOpaque => true
1086+ case _ : PNameAnalyserCustom => true
10401087 case _ => target.isDefined
10411088 }
10421089 }
@@ -1047,18 +1094,13 @@ case class NameAnalyser() {
10471094 n match {
10481095 // Opaque
10491096 case _ : PNameAnalyserOpaque =>
1050- opaque -= 1
1051- case _ if opaque > 0 =>
1097+ ctx.opaque -= 1
1098+ case _ if ctx.opaque > 0 =>
1099+ // Custom
1100+ case c : PNameAnalyserCustom =>
1101+ c.nameUp(ctx)
10521102 // Regular
1053- case _ : PScope =>
1054- val popMap = localDeclarationMaps.get(curScope.scopeId).get
1055- val newScope = scopeStack.pop()
1056- curScope = newScope
1057-
1058- val clashing = getMap().merge(popMap)
1059- clashing.foreach { case (clashing, unique) =>
1060- messages ++= FastMessaging .message(clashing.idndef, s " duplicate identifier ` ${clashing.idndef.name}` at ${clashing.idndef.pos._1} and at ${unique.idndef.pos._1}" )
1061- }
1103+ case _ : PScope => ctx.popScope()
10621104 case _ =>
10631105 }
10641106 }
@@ -1078,18 +1120,8 @@ case class NameAnalyser() {
10781120 // If we started from some inner scope, walk all the way back out to the whole program
10791121 // with a variation of nodeUpNameCollectorVisitor
10801122 if (initialCurScope != null ) {
1081- assert(initialCurScope == curScope)
1082-
1083- while (curScope != null ) {
1084- val popMap = localDeclarationMaps.get(curScope.scopeId).get
1085- curScope.getAncestor[PScope ] match {
1086- case Some (newScope) =>
1087- curScope = newScope
1088- case None =>
1089- curScope = null
1090- }
1091- getMap().merge(popMap)
1092- }
1123+ assert(initialCurScope == ctx.curScope)
1124+ ctx.finish()
10931125 }
10941126 }
10951127
0 commit comments