forked from chipsalliance/verible
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscope_resolver.h
156 lines (129 loc) · 5.53 KB
/
scope_resolver.h
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VERIBLE_VERILOG_TOOLS_KYTHE_SCOPE_RESOLVER_H_
#define VERIBLE_VERILOG_TOOLS_KYTHE_SCOPE_RESOLVER_H_
#include <optional>
#include <string>
#include <utility>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/container/node_hash_map.h"
#include "absl/strings/string_view.h"
#include "verilog/tools/kythe/kythe_facts.h"
namespace verilog {
namespace kythe {
// VName tied to the Scopes where it's defined and instantiated.
struct ScopedVname {
// Where this type was defined.
SignatureDigest type_scope;
// Where the variable of this type was instantiated (or equal to the
// type_scope in case this VName is a type definition).
SignatureDigest instantiation_scope;
VName vname;
bool operator==(const ScopedVname &other) const {
return type_scope == other.type_scope &&
instantiation_scope == other.instantiation_scope &&
vname == other.vname;
}
};
template <typename H>
H AbslHashValue(H state, const ScopedVname &v) {
return H::combine(std::move(state), v.type_scope, v.instantiation_scope,
v.vname.signature.Digest());
}
// ScopeResolver enables resolving a symbol to its definition (to make it
// possible to distinguish one variable or type declaration from another). This
// is done by tracking the program scopes -- syntax elements like function,
// modules and loops create scopes which can contain variables. Multiple
// variables of equal name can co-exist in different scopes.
//
// The resolver keeps track of the active scope. Each scope encodes the whole
// hierarcy. In the following example
//
// package my_pkg;
//
// class my_class;
// int my_var;
// virtual function int my_function();
// return my_var;
// endfunction
// endclass
//
// endpackage : my_pkg
//
// We have the following scopes:
// /my_pkg
// /my_pkg/my_class
// /my_pkg/my_class/my_function
// Scope resolver marks `my_var` as the member of /my_pkg/my_class and is able
// to resolve its reference inside `my_function` (by exploring the scopes bottom
// up and comparing the substrings).
class ScopeResolver {
public:
explicit ScopeResolver(const Signature &top_scope) {
SetCurrentScope(top_scope);
}
ScopeResolver(const ScopeResolver &) = delete;
ScopeResolver(ScopeResolver &&) = delete;
ScopeResolver &operator=(const ScopeResolver &) = delete;
ScopeResolver &operator=(ScopeResolver &&) = delete;
void SetCurrentScope(const Signature &scope);
const Signature &CurrentScope() { return current_scope_; }
// Returns the scope and definition of the symbol under the given name. The
// search is restricted to the current scope.
std::optional<ScopedVname> FindScopeAndDefinition(absl::string_view name);
// Returns the scope and definition of the symbol under the given name. The
// search is restricted to the provided scope.
std::optional<ScopedVname> FindScopeAndDefinition(
absl::string_view name, const SignatureDigest &scope);
static SignatureDigest GlobalScope() { return Signature("").Digest(); }
// Adds the members of the given scope to the current scope.
void AppendScopeToCurrentScope(const SignatureDigest &source_scope);
// Adds the members of the source scope to the destination scope.
void AppendScopeToScope(const SignatureDigest &source_scope,
const SignatureDigest &destination_scope);
// Removes the given VName from the current scope.
void RemoveDefinitionFromCurrentScope(const VName &vname);
// Adds a definition & its type to the current scope.
void AddDefinitionToCurrentScope(const VName &new_member,
const SignatureDigest &type_scope);
// Adds a definition without external type to the current scope.
void AddDefinitionToCurrentScope(const VName &new_member);
const absl::flat_hash_set<VName> &ListScopeMembers(
const SignatureDigest &scope_digest) const;
// Returns human readable description of the scope.
std::string ScopeDebug(const SignatureDigest &scope) const;
const SignatureDigest &CurrentScopeDigest() const {
return current_scope_digest_;
}
// When set, the scope resolver will collect human readable descriptions of
// the scope for easier debugging.
void EnableDebug() { enable_debug_ = true; }
private:
// Mapping from the symbol name to all scopes where it's present.
absl::flat_hash_map<std::string, absl::flat_hash_set<ScopedVname>>
variable_to_scoped_vname_;
// Mapping from scope to all its members. NOTE: requires pointer stability!
absl::node_hash_map<SignatureDigest, absl::flat_hash_set<VName>>
scope_to_vnames_;
// Maps the scope to the human readable description. Available only when debug
// is enabled.
absl::flat_hash_map<SignatureDigest, std::string> scope_to_string_debug_;
SignatureDigest current_scope_digest_;
Signature current_scope_;
bool enable_debug_ = false;
};
} // namespace kythe
} // namespace verilog
#endif // VERIBLE_VERILOG_TOOLS_KYTHE_SCOPE_RESOLVER_H_