Wiki

root/cobra/trunk/Source/Vars.cobra

Revision 2584, 6.3 KB (checked in by Charles.Esterbrook, 10 months ago)

Minor. Stub out support for reporting unused parameters.
ticket:279
credit:maboiteaspam,Charles

  • Property svn:eol-style set to native
Line 
1"""
2For ClassVar, see Members.cobra.
3"""
4
5interface IVar inherits INamedNode is partial
6
7    pro type as IType?
8
9    pro isAssignedTo as bool
10        """
11        Defaults to false and is set to true when an assignment to the variable is encountered.
12        This can then be inspected to generate warnings.
13        """
14
15    pro ifInheritsStack as Stack<of IType>
16
17    def attemptAssignmentOf(type as IType) as bool
18        """
19        Attempts assignment of an expression with the given type which is incompatible with
20        .type, by working back through the if-inherits stack. If successful, the if-inherits
21        stack will be shorter and `true` is returned.
22        """
23        require type <> .type
24
25
26class AbstractLocalVar
27    is abstract, partial
28    inherits NamedNode
29    implements IVar
30    """
31    The base class for Param and LocalVar.
32    """
33
34    invariant .name.length
35   
36    var _type as IType?
37    var _typeNode as ITypeProxy?
38    var _isTracked as bool
39    var _ifInheritsStack = Stack<of IType>()
40    var _isAssignedTo as bool
41    var _backEndName as String
42    var _useBackEndNameStack = Stack<of String>()  # TODO: for if-inherits
43
44    cue init(token as IToken, type as IType)
45        require token.text.length
46        base.init(token, token.text)
47        _type = type
48        assert not _type inherits NameSpace  # TODO: can remove with NameSpace is no longer an IType
49        _init
50
51    cue init(token as IToken, typeNode as ITypeProxy)
52        require token.text.length
53        base.init(token, token.text)
54        _typeNode = typeNode
55        _init
56
57    cue init(name as String, typeNode as ITypeProxy)
58        require name.length
59        base.init(name)
60        _typeNode = typeNode
61        _init
62
63    def _init
64        assert .name.length
65        _isTracked = false
66        if .isImplicit
67            _backEndName = .name
68        else
69            _backEndName = SharpBackEndUtils.backEndNameForLocalVarName(.name# todo-backend
70        _useBackEndNameStack.push(_backEndName)
71
72    get englishName as String is abstract
73
74    pro ifInheritsStack from var
75
76    pro isAssignedTo from var
77
78    pro isTracked from var
79
80    get useBackEndNameStack from var
81
82    def addMinFields
83        base.addMinFields
84        .addField('isTracked', _isTracked)
85
86    def addRefFields
87        base.addRefFields
88        .addField('typeNode', _typeNode)
89        .addField('type', _type)
90
91    def attemptAssignmentOf(type as IType) as bool
92        if _ifInheritsStack.count == 0
93            return false
94        stack = Stack<of IType>(Stack<of IType>(_ifInheritsStack))
95        assert stack.peek == _ifInheritsStack.peek
96        count = 0
97        post while stack.count and not type.isAssignableTo(stack.peek)
98            stack.pop
99            count += 1
100        if count or type.isAssignableTo(_type to !)
101            _ifInheritsStack = stack
102            # tell each IfStmt not to pop the if-inherits stack since the assignment did so
103            for node in .compiler.nodeStack
104                if node inherits IfStmt
105                    if node.ifInheritsVar is this
106                        node.doNotPopIfInheritsStack
107                        count -= 1
108                        if count == 0, break
109            return true
110        else
111            return false
112
113    def toString as String is override
114        type = if(_type, .type.name, "(no type)")
115        return '[.getType.name]([.serialNum], [.token], [.name], [type])'
116
117    def _bindInt
118        base._bindInt
119        _resolveType
120        assert _type
121
122    def _bindImp
123        base._bindImp
124        _resolveType
125
126    def _resolveType
127        require _type or _typeNode
128        if _type
129            return
130        if _typeNode inherits IType
131            _type = _typeNode
132            return
133        _type = _typeNode.realType
134        assert _type  # since _realType returns IType (not IType?) this should always pass
135
136    pro type as IType
137        get
138            require _type
139            return if(_ifInheritsStack.count, _ifInheritsStack.peek, _type to !)
140        set
141            require .compiler
142            if value <> _type
143                assert _type is nil or _type is .compiler.unspecifiedType or _type is .compiler.passThroughType
144                assert not _ifInheritsStack.count
145                _type = value
146
147    get typeNode from var
148
149    get typeForIdentifier as IType is override
150        return .type
151
152    get typeForReceiver as IType is override
153        assert _type
154        return if(_ifInheritsStack.count, _ifInheritsStack.peek, _type to !)
155
156
157enum Direction
158    In
159    Out
160    InOut
161
162
163class Param inherits AbstractLocalVar is partial
164
165    cue init(token as IToken, type as IType)
166        base.init(token, type)
167
168    cue init(token as IToken, typeNode as ITypeProxy)
169        base.init(token, typeNode)
170   
171    cue init(name as String, typeNode as ITypeProxy)
172        base.init(name, typeNode)
173
174    def _init is override
175        base._init
176        _attributes = AttributeList()
177
178    pro attributes from var as AttributeList
179
180    get englishName as String is override
181        return 'parameter'
182
183    pro isMissingType from var as bool
184        """
185        Returns true if parameter was declared with no type.
186        Currently, such a parameter is given the `dynamic?` type.
187        In the future, the type may be inferred for an anon method in the context it is used (a specific delegate or event).
188        """
189
190    pro isDeclaredAsUnused from var as bool
191        """
192        Returns true if parameter was declared as unused.
193        """
194
195    pro isAnonymousParam from var as bool
196
197    pro direction from var as Direction
198
199    get isInOut as bool
200        return .direction == Direction.InOut
201
202    get isOut as bool
203        return .direction == Direction.Out
204
205    def constructedFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as Param
206        ensure
207            result is not this
208        body
209            assert .ifInheritsStack.count == 0
210            p = .memberwiseClone to Param
211            p._ifInheritsStack = Stack<of IType>()
212            p._type = p._type.secondaryConstructedTypeFor(box, gpToType)
213            return p
214
215    def _bindInt
216        base._bindInt
217        for attrib in .attributes
218            try
219                attrib.bindInt
220            catch ne as NodeException
221                .compiler.recordError(ne)
222
223    def _bindImp
224        base._bindImp
225        for attrib in .attributes
226            try
227                attrib.bindImp
228            catch ne as NodeException
229                .compiler.recordError(ne)
230
231           
232class LocalVar inherits AbstractLocalVar is partial
233
234    cue init(token as IToken, type as IType)
235        base.init(token, type)
236
237    cue init(token as IToken, typeNode as ITypeProxy)
238        base.init(token, typeNode)
239
240    def addMinFields
241        base.addMinFields
242        .addField('isTracked', _isTracked)
243
244    get englishName as String is override
245        return 'local variable'
246
247    get isForContract as bool
248        return .isForRequire or .isForEnsure
249
250    pro isForRequire from var = false
251
252    pro isForEnsure from var = false
253
254
255class ResultVar
256    is partial
257    inherits LocalVar
258    """
259    The implicit variable `result` used in `ensure` blocks.
260    """
261
262    cue init(token as IToken, codePart as AbstractMethod)
263        base.init(_makeToken(token, codePart), codePart.resultType)
264        .isImplicit = true
265        _backEndName = codePart.backEndResultVarName
266
267    def _makeToken(token as IToken, codePart as AbstractMethod) as IToken is shared
268        token = token.copy
269        token.text = 'result'
270        return token
271
272    get englishName as String is override
273        return 'implicit result variable'
Note: See TracBrowser for help on using the browser.