forked from mozart/mozart2-compiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBindingAnalysis.oz
195 lines (194 loc) · 6.8 KB
/
BindingAnalysis.oz
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
%%%
%%% Author:
%%% Leif Kornstaedt <[email protected]>
%%%
%%% Copyright:
%%% Leif Kornstaedt, 1997
%%%
%%% Last change:
%%% $Date$ by $Author$
%%% $Revision$
%%%
%%% This file is part of Mozart, an implementation of Oz 3:
%%% http://www.mozart-oz.org
%%%
%%% See the file "LICENSE" or
%%% http://www.mozart-oz.org/LICENSE.html
%%% for information on usage and redistribution
%%% of this file, and for a DISCLAIMER OF ALL
%%% WARRANTIES.
%%%
local
BindingAnalysisError = 'binding analysis error'
BindingAnalysisWarning = 'binding analysis warning'
in
class BindingAnalysis
prop final
attr env: nil freeVariablesOfQuery: unit
feat MyTopLevel MyReporter WarnRedecl WarnShadowedVars
meth init(TopLevel Reporter State)
env <- nil
freeVariablesOfQuery <- {NewDictionary}
self.MyTopLevel = TopLevel
self.MyReporter = Reporter
self.WarnRedecl = {State getSwitch(warnredecl $)}
self.WarnShadowedVars = {State getSwitch(warnshadow $)}
end
meth openScope() X in
env <- {NewDictionary}#X#X|@env
end
meth getVars(?Vs) Env = @env in
_#Vs#nil|_ = Env
end
meth getAllVariables($)
{Record.foldR
{FoldR @env
fun {$ D#_#_ Vs0}
{Adjoin Vs0 {Dictionary.toRecord x D}}
end x}
fun {$ X In}
X|In
end nil}
end
meth closeScope(?Vs) Env = @env Dr in
_#Vs#nil|Dr = Env
env <- Dr
end
meth bind(PrintName Coord ?V) X Env = @env D#Hd#Tl|Dr = Env in
if self.WarnShadowedVars then
if {Some
%% Check for Variable in outer scopes
case @env of _|TailEnv then TailEnv else nil end
fun {$ D#_#_} {Dictionary.member D PrintName} end}
then
{self.MyReporter warn(coord: Coord
kind: BindingAnalysisWarning
msg: ('shadowing variable `'#
pn(PrintName)#'\''))}
end
end
if self.WarnRedecl orelse self.WarnShadowedVars then TopV in
{self.MyTopLevel lookupVariableInEnv(PrintName ?TopV)}
case TopV of undeclared then skip
else
{self.MyReporter warn(coord: Coord
kind: BindingAnalysisWarning
msg: ('redeclaring top-level variable `'#
pn(PrintName)#'\''))}
end
end
X = {Dictionary.condGet D PrintName undeclared}
case X of undeclared then NewTl in
V = {New Core.userVariable init(PrintName Coord)}
{Dictionary.put D PrintName V}
Tl = V|NewTl
env <- D#Hd#NewTl|Dr
else
V = X
end
end
meth bindImport(PrintName Coord Features ?V)
X Env = @env D#Hd#Tl|Dr = Env
in
X = {Dictionary.condGet D PrintName undeclared}
case X of undeclared then NewTl in
V = {New Core.restrictedVariable init(PrintName Features Coord)}
{Dictionary.put D PrintName V}
Tl = V|NewTl
env <- D#Hd#NewTl|Dr
else
{self.MyReporter
error(coord: Coord kind: BindingAnalysisError
msg: 'variable '#pn(PrintName)#' imported more than once')}
V = X
end
end
meth refer(PrintName Coord ?VO) V in
BindingAnalysis, Refer(PrintName Coord @env ?V)
case V of undeclared then
{self.MyReporter
error(coord: Coord kind: BindingAnalysisError
msg: 'variable '#pn(PrintName)#' not introduced')}
{BindingAnalysis, bind(PrintName Coord $) occ(Coord ?VO)}
else
if {V isRestricted($)} then
{self.MyReporter
error(coord: Coord kind: BindingAnalysisError
msg: 'illegal use of imported variable '#pn(PrintName))}
end
{V occ(Coord ?VO)}
end
end
meth referImport(PrintName Coord Feature ?IsImport ?VO) V in
BindingAnalysis, Refer(PrintName Coord @env ?V)
case V of undeclared then
{self.MyReporter
error(coord: Coord kind: BindingAnalysisError
msg: 'variable '#pn(PrintName)#' not introduced')}
IsImport = false
{BindingAnalysis, bind(PrintName Coord $) occ(Coord ?VO)}
else GV in
{V isRestricted(?IsImport)}
if {V isDenied(Feature ?GV $)} then
{self.MyReporter
error(coord: Coord kind: BindingAnalysisError
msg: 'illegal use of imported variable '#pn(PrintName)
items: [hint(l: 'Unknown feature' m: oz(Feature))])}
end
if GV \= unit then
{GV occ(Coord ?VO)}
else
{V occ(Coord ?VO)}
end
end
end
meth referUnchecked(PrintName Coord ?VO) V in
BindingAnalysis, Refer(PrintName Coord @env ?V)
{V occ(Coord ?VO)}
end
meth referExpansionOcc(PrintName Coord ?VO) V in
BindingAnalysis, Refer(PrintName Coord @env ?V)
case V of undeclared then
VO = undeclared
else
{V occ(Coord ?VO)}
end
end
meth Refer(PrintName Coord Env ?V)
case Env of E|Er then X D#_#_ = E in
X = {Dictionary.condGet D PrintName undeclared}
case X of undeclared then
BindingAnalysis, Refer(PrintName Coord Er ?V)
else
V = X
end
[] nil then
{self.MyTopLevel lookupVariableInEnv(PrintName ?V)}
case V of undeclared then skip
else {Dictionary.put @freeVariablesOfQuery PrintName V}
end
end
end
meth generate(Origin Coord ?V) Env = @env D#Hd#Tl|Dr = Env NewTl in
V = {New Core.generatedVariable init(Origin Coord)}
Tl = V|NewTl
env <- D#Hd#NewTl|Dr
end
meth generateForOuterScope(Origin Coord ?V)
Env = @env E1|D#Hd#Tl|Dr = Env NewTl in
%% This method is provided to generate a variable that is not
%% to be declared in the currently open scope, but in the scope
%% surrounding it.
V = {New Core.generatedVariable init(Origin Coord)}
Tl = V|NewTl
env <- E1|D#Hd#NewTl|Dr
end
meth isBoundLocally(PrintName $) Env = @env D#_#_|_ = Env in
{Dictionary.member D PrintName}
end
meth getFreeVariablesOfQuery(?Vs)
Vs = {Dictionary.items @freeVariablesOfQuery}
freeVariablesOfQuery <- {NewDictionary}
end
end
end