File: ExpressionTypeVisitor.boo

package info (click to toggle)
monodevelop-boo 2.4-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 528 kB
  • ctags: 57
  • sloc: makefile: 246; xml: 193; sh: 160
file content (269 lines) | stat: -rw-r--r-- 9,598 bytes parent folder | download
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#region license
// Copyright (c) 2004-2005, Daniel Grunwald (daniel@danielgrunwald.de)
// Copyright (c) 2005, Peter Johanson (latexer@gentoo.org)
// All rights reserved.
//
// The BooBinding.Parser code is originally that of Daniel Grunwald
// (daniel@danielgrunwald.de) from the SharpDevelop BooBinding. The code has
// been imported here, and modified, including, but not limited to, changes
// to function with MonoDevelop, additions, refactorings, etc.
//
// BooBinding is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// BooBinding is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with BooBinding; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#endregion
/*
namespace BooBinding.Parser

import System
import System.Collections
import MonoDevelop.Projects.Dom
import MonoDevelop.Projects.Dom.Parser
import Boo.Lang.Compiler.Ast

class ExpressionTypeVisitor(DepthFirstVisitor):
	protected override def OnError(node as Node, error as Exception):
		Error (error.ToString ())
		super(node, error)
	
	private def Log (message):
		BooParser.Log (self.GetType (), message)
	
	private def Error (message):
		BooParser.Error (self.GetType (), message)

	[Property(ReturnType)]
	_returnType as IReturnType
	
	[Property(ReturnClass)]
	_returnClass as IClass
	
	[Property(Resolver)]
	_resolver as Resolver
	
	private def CreateReturnType(fullClassName as string):
		_returnClass = null
		if fullClassName == null:
			_returnType = null
		else:
			_returnType = BooBinding.Parser.ReturnType(fullClassName)
	
	private def CreateReturnType(reference as TypeReference):
		_returnClass = null
		if reference == null:
			_returnType = null
		else:
			_returnType = BooBinding.Parser.ReturnType(reference)
	
	private def CreateReturnType(c as IClass):
		_returnClass = c
		if c == null:
			_returnType = null
		else:
			_returnType = BooBinding.Parser.ReturnType(c)
	
	private def SetReturnType(r as IReturnType):
		_returnClass = null
		_returnType = r
	
	private def Debug(node):
		if node == null:
			Log ("-- null --")
		else:
			Log ("${node.ToString()} - ${node.GetType().FullName}")
	
	override def OnBlockExpression(node as BlockExpression):
		Debug(node)
		CreateReturnType("System.Delegate")
	
	override def OnMethodInvocationExpression(node as MethodInvocationExpression):
		Debug(node)
		Debug(node.Target)
		if node.Target isa MemberReferenceExpression:
			// call a method on another object
			mre as MemberReferenceExpression = node.Target
			Visit(mre.Target)
			if _returnClass == null and _returnType != null:
				_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName, true)
			return if ProcessMethod(node, mre.Name, _returnClass)
			// try if the MemberReferenceExpression is a fully qualified class name (constructor call)
			ProcessMemberReferenceExpression(mre.Name)
			CreateReturnType(_returnClass)
		elif node.Target isa ReferenceExpression:
			re as ReferenceExpression = node.Target
			// try if it is a method on the current object
			return if ProcessMethod(node, re.Name, _resolver.CallingClass)
			// try if it is a builtin method
			return if ProcessMethod(node, re.Name, _resolver.BuiltinClass)
			// try if it is a class name -> constructor
			CreateReturnType(_resolver.SearchType(re.Name, true))
		else:
			SetReturnType(null)
	
	private def ProcessMethod(node as MethodInvocationExpression, name as string, c as IClass) as bool:
		return false if c == null
		possibleOverloads = FindMethods(c, name, node.Arguments.Count)
		Log ("found ${possibleOverloads.Count} overloads (multiple overloads not supported yet)")
		if possibleOverloads.Count >= 1:
			SetReturnType(cast(IMethod, possibleOverloads[0]).ReturnType)
			return true
		
		return false
	
	private def FindMethods(c as IClass, name as string, arguments as int):
		possibleOverloads = ArrayList()
		//for cl as IClass in c.ClassInheritanceTree:
		for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(c):
			for m as IMethod in cl.Methods:
				if m.Parameters.Count == arguments and name == m.Name:
					possibleOverloads.Add(m)
		return possibleOverloads
	
	override def OnSlicingExpression(node as SlicingExpression):
		Debug(node)
		Visit(node.Target)
		slice as Slice = node.Indices[0]
		if (slice.End != null):
			// Boo slice, returns a part of the source -> same type as source
			return
		if _returnType != null and _returnType.ArrayDimensions != null and _returnType.ArrayDimensions.Length > 0:
			SetReturnType(BooBinding.Parser.ReturnType(_returnType.FullyQualifiedName, _returnType.ArrayDimensions[0 : _returnType.ArrayDimensions.Length - 1], 0))
			return
		if _returnClass == null and _returnType != null:
			_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName)
		if _returnClass != null:
			indexers = FindIndexer(_returnClass, 1)
			if indexers.Count > 0:
				SetReturnType(cast(IIndexer, indexers[0]).ReturnType)
				return
		SetReturnType(null)
	
	private def FindIndexer(c as IClass, arguments as int):
		possibleOverloads = ArrayList()
		//for cl as IClass in c.ClassInheritanceTree:
		for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(c):
			for m as IIndexer in cl.Indexer:
				if m.Parameters.Count == arguments:
					possibleOverloads.Add(m)
		return possibleOverloads
	
	override def OnBinaryExpression(node as BinaryExpression):
		Debug(node)
		CombineTypes(node.Left, node.Right)
	
	override def OnConditionalExpression(node as ConditionalExpression):
		Debug(node)
		CombineTypes(node.TrueValue, node.FalseValue)
	
	private def CombineTypes(a as Expression, b as Expression):
		Visit(a)
	
	override def OnReferenceExpression(node as ReferenceExpression):
		// Resolve reference (to a variable, field, parameter or type)
		rt = _resolver.GetTypeFromLocal(node.Name)
		if rt != null:
			SetReturnType(rt)
			return

		return if ProcessMember(node.Name, _resolver.CallingClass)
		if _resolver.IsNamespace(node.Name):
			SetReturnType(NamespaceReturnType(node.Name))
		else:
			CreateReturnType(_resolver.SearchType(node.Name))
	
	override def OnMemberReferenceExpression(node as MemberReferenceExpression):
		Debug(node)
		Visit(node.Target)
		ProcessMemberReferenceExpression(node.Name)
	
	private def ProcessMemberReferenceExpression(name as string):
	"""Gets the return type of the MemberReferenceExpression with the specified name
	on the current return type."""
		if _returnType isa NamespaceReturnType:
			name = _returnType.FullyQualifiedName + '.' + name
			if _resolver.IsNamespace(name):
				SetReturnType(NamespaceReturnType(name))
			else:
				CreateReturnType(_resolver.SearchType(name))
			return
		if _returnClass == null and _returnType != null:
			_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName)
		return if ProcessMember(name, _returnClass)
		SetReturnType(null)
	
	private def ProcessMember(name as string, parentClass as IClass):
		return false if parentClass == null
		for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(parentClass):
			for c as IClass in cl.InnerClasses:
				if c.Name == name:
					CreateReturnType(c)
					return true
			for f as IField in cl.Fields:
				if f.Name == name:
					SetReturnType(f.ReturnType)
					return true
			for p as IProperty in cl.Properties:
				if p.Name == name:
					SetReturnType(p.ReturnType)
					return true
			for m as IMethod in cl.Methods:
				if m.Name == name:
					CreateReturnType("System.Delegate")
					return true
		return false
	
	override def OnTimeSpanLiteralExpression(node as TimeSpanLiteralExpression):
		CreateReturnType("System.TimeSpan")
	
	override def OnIntegerLiteralExpression(node as IntegerLiteralExpression):
		CreateReturnType("System.Int32")
	
	override def OnDoubleLiteralExpression(node as DoubleLiteralExpression):
		CreateReturnType("System.Double")
	
	override def OnNullLiteralExpression(node as NullLiteralExpression):
		CreateReturnType("System.Object")
	
	override def OnStringLiteralExpression(node as StringLiteralExpression):
		CreateReturnType("System.String")
	
	override def OnSelfLiteralExpression(node as SelfLiteralExpression):
		CreateReturnType(_resolver.CallingClass)
	
	override def OnSuperLiteralExpression(node as SuperLiteralExpression):
		CreateReturnType(_resolver.ParentClass)
	
	override def OnBoolLiteralExpression(node as BoolLiteralExpression):
		CreateReturnType("System.Boolean")
	
	override def OnRELiteralExpression(node as RELiteralExpression):
		CreateReturnType("System.Text.RegularExpressions.Regex")
	
	override def OnHashLiteralExpression(node as HashLiteralExpression):
		CreateReturnType("System.Collections.Hashtable")
	
	override def OnListLiteralExpression(node as ListLiteralExpression):
		CreateReturnType("System.Collections.ArrayList")
	
	override def OnArrayLiteralExpression(node as ArrayLiteralExpression):
		CreateReturnType("System.Array")
	
	override def OnTryCastExpression(node as TryCastExpression):
		CreateReturnType(node.Type)
	
	override def OnCastExpression(node as CastExpression):
		CreateReturnType(node.Type)
	
	override def OnTypeofExpression(node as TypeofExpression):
		CreateReturnType("System.Type")
*/