1 #Region "Microsoft.VisualBasic::5dba054f8202fb1c3e062be7fe3156d2, Microsoft.VisualBasic.Core\Language\Linq\Vectorization\VectorShadows.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class VectorShadows
35     
36     '         Constructor: (+1 OverloadsSub New
37     
38     '         Function: [As], binaryOperatorSelfLeft, CreateVector, GetDynamicMemberNames, GetJson
39     '                   TryBinaryOperation, (+2 OverloadsTryGetMember, TryInvokeMember, TrySetMember, TryUnaryOperation
40     
41     '         Sub: writeBuffer
42     
43     '         Operators: \, (+2 OverloadsLike
44     
45     
46     ' /********************************************************************************/
47
48 #End Region
49
50 Imports System.Dynamic
51 Imports System.Reflection
52 Imports System.Runtime.CompilerServices
53 Imports Microsoft.VisualBasic.Emit.Delegates
54 Imports Microsoft.VisualBasic.Linq
55 Imports Microsoft.VisualBasic.Scripting.Runtime
56 Imports Microsoft.VisualBasic.Scripting.TokenIcer
57 Imports Microsoft.VisualBasic.Serialization.JSON
58
59 Namespace Language.Vectorization
60
61     ''' <summary>
62     ''' Vectorization programming language feature for VisualBasic
63     ''' </summary>
64     ''' <typeparam name="T"></typeparam>
65     Public Class VectorShadows(Of T) : Inherits Vector(Of T)
66         Implements IEnumerable(Of T)
67
68         ''' <summary>
69         ''' 无参数的属性
70         ''' </summary>
71         Protected linq As DataValue(Of T)
72         Protected ReadOnly type As New VectorSchemaProvider(GetType(T))
73
74         Default Public Overloads Property Item(exp$) As Object
75             Get
76                 If exp = "Me" Then
77                     Return Me
78                 ElseIf type.PropertyNames.IndexOf(exp) > -1 Then
79                     Return linq(exp)
80                 Else
81                     Return MyBase.Item(exp)
82                 End If
83             End Get
84             Set(value)
85                 If exp = "Me" Then
86                     buffer = DirectCast(value, IEnumerable(Of T)).ToArray
87                 ElseIf type.PropertyNames.IndexOf(exp) > -1 Then
88                     linq(exp) = value
89                 Else
90                     MyBase.Item(exp) = DirectCast(value, IEnumerable(Of T)).AsList
91                 End If
92             End Set
93         End Property
94
95         Public Function [As](Of V)() As V()
96             Return buffer.As(Of V)
97         End Function
98
99 #Region ""
100         Default Public Overloads Property Item(booleans As IEnumerable(Of Boolean)) As VectorShadows(Of T)
101             Get
102                 Return New VectorShadows(Of T)(MyBase.Item(booleans))
103             End Get
104             Set(value As VectorShadows(Of T))
105                 MyBase.Item(booleans) = value
106             End Set
107         End Property
108 #End Region
109
110         Sub New(source As IEnumerable(Of T))
111             Call writeBuffer(source)
112         End Sub
113
114         Protected Sub writeBuffer(seq As IEnumerable(Of T))
115             buffer = seq.ToArray
116             linq = New DataValue(Of T)(buffer)
117         End Sub
118
119         ''' <summary>
120         ''' Returns property names and function names
121         ''' </summary>
122         ''' <returns></returns>
123         ''' 
124         <MethodImpl(MethodImplOptions.AggressiveInlining)>
125         Public Overrides Function GetDynamicMemberNames() As IEnumerable(Of String)
126             Return type.GetDynamicMemberNames
127         End Function
128
129         ''' <summary>
130         ''' Vector array json string
131         ''' </summary>
132         ''' <returns></returns>
133         Public Function GetJson() As String
134             Return Me.ToArray.GetJson
135         End Function
136
137         ''' <summary>
138         ''' Create a generic vector for a specific .NET <paramref name="type"/>
139         ''' </summary>
140         ''' <param name="data"></param>
141         ''' <param name="type"></param>
142         ''' <returns></returns>
143         Public Shared Function CreateVector(data As IEnumerable, type As Type) As Object
144             With GetType(VectorShadows(Of )).MakeGenericType(type)
145                 Dim vector = Activator.CreateInstance(.ByRef, {data.CreateArray(type)})
146                 Return vector
147             End With
148         End Function
149
150 #Region "Property Get/Set"
151
152         ''' <summary>
153         ''' Property Get
154         ''' </summary>
155         ''' <param name="binder"></param>
156         ''' <param name="result"></param>
157         ''' <returns></returns>
158         <MethodImpl(MethodImplOptions.AggressiveInlining)>
159         Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As ObjectAs Boolean
160             Return TryGetMember(binder.Name, result)
161         End Function
162
163         ''' <summary>
164         ''' 大小写不敏感
165         ''' </summary>
166         ''' <param name="name$"></param>
167         ''' <param name="result"></param>
168         ''' <returns></returns>
169         Public Overloads Function TryGetMember(name$, ByRef result As ObjectAs Boolean
170             With type.TryGetMember(name, False)
171                 If .IsNothing Then
172                     Return False
173                 Else
174                     Dim type As Type = .PropertyType
175                     Dim source = linq.Evaluate(name)
176                     result = CreateVector(DirectCast(source, IEnumerable), type)
177                     Return True
178                 End If
179             End With
180         End Function
181
182         ''' <summary>
183         ''' Property Set
184         ''' </summary>
185         ''' <param name="binder"></param>
186         ''' <param name="value"></param>
187         ''' <returns></returns>
188         Public Overrides Function TrySetMember(binder As SetMemberBinder, value As ObjectAs Boolean
189             If type.TrySetMember(binder) Is Nothing Then
190                 Return False
191             Else
192                 linq.Evaluate(binder.Name) = value
193                 Return True
194             End If
195         End Function
196 #End Region
197
198 #Region "Method/Function"
199
200         ''' <summary>
201         ''' Function invoke
202         ''' </summary>
203         ''' <param name="binder"></param>
204         ''' <param name="args"></param>
205         ''' <param name="result"></param>
206         ''' <returns></returns>
207         Public Overrides Function TryInvokeMember(binder As InvokeMemberBinder, args() As ObjectByRef result As ObjectAs Boolean
208             Dim method As MethodInfo = type.TryInvokeMember(binder, args)
209
210             If method Is Nothing Then
211                 Return False
212             Else
213                 result = Me.Select(Function(o) method.Invoke(o, args))
214                 result = CreateVector(DirectCast(result, IEnumerable), method.ReturnType)
215                 Return True
216             End If
217         End Function
218 #End Region
219
220 #Region "Operator:Unary"
221         Public Overrides Function TryUnaryOperation(binder As UnaryOperationBinder, ByRef result As ObjectAs Boolean
222             Dim method As MethodInfo = type.TryUnaryOperation(binder)
223
224             If method Is Nothing Then
225                 Return False
226             Else
227                 result = Me.Select(Function(x) method.Invoke(Nothing, {x}))
228                 result = CreateVector(DirectCast(result, IEnumerable), method.ReturnType)
229             End If
230
231             Return True
232         End Function
233 #End Region
234
235 #Region "Operator:Binary"
236
237         ''' <summary>
238         ''' Fix for &amp; operator not defined!
239         ''' </summary>
240         ''' <param name="vector"></param>
241         ''' <param name="obj"></param>
242         ''' <returns></returns>
243         Public Overloads Shared Operator &(vector As VectorShadows(Of T), obj As ObjectAs Object
244             Dim type As Type = obj.GetType
245             Dim isVector As Boolean = False
246             Dim op As MethodInfo = vector.type.Concatenate(type, isVector)
247
248             If op Is Nothing Then
249                 If vector.type Is GetType(String) Then
250                     If type.ImplementInterface(GetType(IEnumerable(Of String))) Then
251                         ' 如果是字符串的集合,则分别添加字符串
252                         Dim out$() = New String(vector.Length - 1) {}
253
254                         For Each s In DirectCast(obj, IEnumerable(Of String)).SeqIterator
255                             out(s) = DirectCast(CObj(vector.buffer(s)), String) & s.value
256                         Next
257
258                         Return New VectorShadows(Of String)(out)
259                     Else
260                         ' 否则直接将目标对象转换为字符串,进行统一添加
261                         Dim s$ = CStr(obj)
262                         Return New VectorShadows(Of String)(
263                             vector _
264                             .Select(Function(o) CStrSafe(o) & s) _
265                             .ToArray)
266                     End If
267                 Else
268                     Throw New NotImplementedException
269                 End If
270             Else
271                 Return binaryOperatorSelfLeft(vector, op, obj, isVector, type)
272             End If
273         End Operator
274
275         Private Shared Function binaryOperatorSelfLeft(vector As VectorShadows(Of T), method As MethodInfo, obj As Object, vectorMode As Boolean, type As Type) As Object
276             If Not method Is Nothing Then
277                 If Not vectorMode Then
278                     obj = vector _
279                     .Select(Function(self) method.Invoke(Nothing, {self, obj})) _
280                     .ToArray
281                     Return CreateVector(DirectCast(obj, IEnumerable), method.ReturnType)
282                 Else
283                     Dim out = New Object(vector.Length - 1) {}
284
285                     For Each o In DirectCast(obj, IEnumerable).SeqIterator
286                         out(o) = method.Invoke(Nothing, {vector.buffer(o), o.value})
287                     Next
288
289                     Return CreateVector(out, method.ReturnType)
290                 End If
291             Else
292                 Throw New NotImplementedException
293             End If
294         End Function
295
296         ''' <summary>
297         ''' Fix for Like operator not defined in Linq.
298         ''' </summary>
299         ''' <param name="vector"></param>
300         ''' <param name="obj"></param>
301         ''' <returns></returns>
302         Public Shared Operator Like(vector As VectorShadows(Of T), obj As ObjectAs Object
303             Dim type As Type = obj.GetType
304             Dim isVector As Boolean = False
305             Dim op As MethodInfo = vector.type.Like(type, isVector)
306
307             If op Is Nothing Then
308
309                 ' string like
310                 If vector.type Is GetType(String) Then
311                     If type Is GetType(String) Then
312                         Dim str$ = obj.ToString
313
314                         Return New VectorShadows(Of Boolean)(vector.Select(Function(s) CStrSafe(s) Like str))
315                     ElseIf type.ImplementInterface(GetType(IEnumerable(Of String))) Then
316                         Dim out As Boolean() = New Boolean(vector.Length - 1) {}
317
318                         For Each s In DirectCast(obj, IEnumerable(Of String)).SeqIterator
319                             out(s) = DirectCast(CObj(vector.buffer(s)), StringLike s.value
320                         Next
321
322                         Return New VectorShadows(Of Boolean)(out)
323                     End If
324                 End If
325
326                 Throw New NotImplementedException
327             Else
328                 Return binaryOperatorSelfLeft(vector, op, obj, isVector, type)
329             End If
330         End Operator
331
332         Public Shared Operator \(vector As VectorShadows(Of T), obj As ObjectAs Object
333             Dim type As Type = obj.GetType
334             Dim isVector As Boolean = False
335             Dim op As MethodInfo = vector.type.Concatenate(type, isVector)
336
337             If op Is Nothing Then
338                 Throw New NotImplementedException
339             Else
340                 Return binaryOperatorSelfLeft(vector, op, obj, isVector, obj.GetType)
341             End If
342         End Operator
343
344         Const left% = 0
345         Const right% = 1
346
347         Public Overrides Function TryBinaryOperation(binder As BinaryOperationBinder, arg As ObjectByRef result As ObjectAs Boolean
348             Dim type As Type = arg.GetType
349             Dim isVector As Boolean = False
350             Dim target As MethodInfo = Me.type.TryBinaryOperation(binder, type, isVector)
351
352             If Not target Is Nothing Then
353                 If Not isVector Then
354                     ' me op arg
355                     result = buffer _
356                         .Select(Function(self) target.Invoke(Nothing, {self, arg}))
357                     result = CreateVector(DirectCast(result, IEnumerable), target.ReturnType)
358
359                     Return True
360                 Else
361                     Dim out = New Object(buffer.Length - 1) {}
362
363                     For Each o In DirectCast(arg, IEnumerable).SeqIterator
364                         out(o) = target.Invoke(Nothing, {buffer(o), o.value})
365                     Next
366                     result = CreateVector(out, target.ReturnType)
367
368                     Return True
369                 End If
370             Else
371                 Return False
372             End If
373         End Function
374 #End Region
375     End Class
376 End Namespace