summaryrefslogtreecommitdiff
path: root/Source/VCExpr/NameClashResolver.ssc
blob: 28a974a6d4322e1fbf8e62c54e6a27baa9a9633b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System;
using System.Text;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Contracts;
using Microsoft.Basetypes;

// Visitor that establishes unique variable (or constant) names in a VCExpr.
// This is done by adding a counter as suffix if name clashes occur

// TODO: also handle type variables here

namespace Microsoft.Boogie.VCExprAST {
  using TEHelperFuns = Microsoft.Boogie.TypeErasure.HelperFuns;

  public class UniqueNamer : ICloneable {

    public UniqueNamer() {
      GlobalNames = new Dictionary<Object!, string!> ();
      LocalNames = TEHelperFuns.ToList(new Dictionary<Object!, string!> ()
                                         as IDictionary<Object!, string!>);
      UsedNames = new Dictionary<string!, bool> ();
      CurrentCounters = new Dictionary<string!, int> ();
    }

    private UniqueNamer(UniqueNamer! namer) {
      GlobalNames = new Dictionary<Object!, string!> (namer.GlobalNames);
      
      List<IDictionary<Object!, string!>!>! localNames =
        new List<IDictionary<Object!, string!>!> ();
      LocalNames = localNames;
      
      foreach (IDictionary<Object!, string!>! d in namer.LocalNames)
        localNames.Add(new Dictionary<Object!, string!> (d));

      UsedNames = new Dictionary<string!, bool> (namer.UsedNames);
      CurrentCounters = new Dictionary<string!, int> (namer.CurrentCounters);
    }

    public Object! Clone() {
      return new UniqueNamer (this);
    }

    ////////////////////////////////////////////////////////////////////////////

    private readonly IDictionary<Object!, string!>! GlobalNames;
    private readonly List<IDictionary<Object!, string!>!>! LocalNames;

    // dictionary of all names that have already been used
    // (locally or globally)
    private readonly IDictionary<string!, bool>! UsedNames;
    private readonly IDictionary<string!, int>! CurrentCounters;

    ////////////////////////////////////////////////////////////////////////////

    public void PushScope() {
      LocalNames.Add(new Dictionary<Object!, string!> ());
    }

    public void PopScope() {
      LocalNames.RemoveAt(LocalNames.Count - 1);
    }    

    ////////////////////////////////////////////////////////////////////////////

    private string! NextFreeName(string! baseName) {
      string! candidate;
      int counter;

      if (CurrentCounters.TryGetValue(baseName, out counter)) {
        candidate = baseName + "@@" + counter;
        counter = counter + 1;
      } else {
        candidate = baseName;
        counter = 0;
      }

      bool dummy;
      while (UsedNames.TryGetValue(candidate, out dummy)) {
        candidate = baseName + "@@" + counter;
        counter = counter + 1;
      }

      UsedNames.Add(candidate, true);
      CurrentCounters[baseName] = counter;
      return candidate;
    }

    // retrieve the name of a thingie; if it does not have a name yet,
    // generate a unique name for it (as close as possible to its inherent
    // name) and register it globally
    public string! GetName(Object! thingie, string! inherentName) {
      string res = this[thingie];

      if (res != null)
        return res;

      // if the object is not yet registered, create a name for it
      res = NextFreeName(inherentName);
      GlobalNames.Add(thingie, res);

      return res;
    }

    [Pure]
    public string this[Object! thingie] { get {
      string res;
      for (int i = LocalNames.Count - 1; i >= 0; --i) {
        if (LocalNames[i].TryGetValue(thingie, out res))
          return res;
      }

      GlobalNames.TryGetValue(thingie, out res);
      return res;
    } }

    public string! GetLocalName(Object! thingie, string! inherentName) {
      string! res = NextFreeName(inherentName);
      LocalNames[LocalNames.Count - 1][thingie] = res;
      return res;
    }
  }
}