1 #Region "Microsoft.VisualBasic::b78c275b4a9348fc00ecfb15990c859c, Microsoft.VisualBasic.Core\Scripting\Runtime\BinaryOperator.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 BinaryOperator
35     
36     '         Properties: Name
37     
38     '         Constructor: (+2 OverloadsSub New
39     '         Function: __invokeInternal, CreateOperator, InvokeSelfLeft, InvokeSelfRight, Match
40     '                   MatchLeft, MatchRight, ToString
41     
42     
43     ' /********************************************************************************/
44
45 #End Region
46
47 Imports System.Reflection
48 Imports System.Runtime.CompilerServices
49 Imports Microsoft.VisualBasic.ComponentModel.Collection.Generic
50 Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel.Repository
51
52 Namespace Scripting.Runtime
53
54     ''' <summary>
55     ''' Binary operator invoker
56     ''' </summary>
57     Public Class BinaryOperator : Implements INamedValue
58
59         ReadOnly methods As MethodInfo()
60
61         ''' <summary>
62         ''' The name of this binary operator
63         ''' </summary>
64         Public Property Name As String Implements IKeyedEntity(Of String).Key
65
66         ''' <summary>
67         ''' 
68         ''' </summary>
69         ''' <param name="[overloads]">重名的运算符函数方法</param>
70         ''' 
71         <MethodImpl(MethodImplOptions.AggressiveInlining)>
72         Sub New([overloads] As MethodInfo())
73             Call Me.New([overloads](Scan0).Name, [overloads])
74         End Sub
75
76         ''' <summary>
77         ''' 可以通过继承<see cref="MethodInfo"/>类型来自定义函数,再使用这个操作符对象应用于脚本运行时环境之中
78         ''' </summary>
79         ''' <param name="name$"></param>
80         ''' <param name="methods"></param>
81         Sub New(name$, methods As MethodInfo())
82             Me.Name = name
83             Me.methods = methods
84         End Sub
85
86         Public Overrides Function ToString() As String
87             If methods.Length = 1 Then
88                 Return Name
89             Else
90                 Return $"{Name} (+{methods.Length} Overloads)"
91             End If
92         End Function
93
94         ''' <summary>
95         ''' ``args op me``.(参数在左边)
96         ''' </summary>
97         ''' <param name="type"></param>
98         ''' <returns></returns>
99         ''' 
100         <MethodImpl(MethodImplOptions.AggressiveInlining)>
101         Public Function MatchLeft(type As Type) As MethodInfo
102             Return Match(type, 0)
103         End Function
104
105         ''' <summary>
106         ''' ``me op args``.(参数在右边)
107         ''' </summary>
108         ''' <param name="type"></param>
109         ''' <returns></returns>
110         ''' 
111         <MethodImpl(MethodImplOptions.AggressiveInlining)>
112         Public Function MatchRight(type As Type) As MethodInfo
113             Return Match(type, 1)
114         End Function
115
116         Public Function Match(type As Type, pos%) As MethodInfo
117             Dim depthMin% = Integer.MaxValue
118             Dim target As MethodInfo = Nothing
119
120             For Each m As MethodInfo In methods
121                 ' 参数在右边,即第二个参数
122                 Dim parm As ParameterInfo = m.GetParameters(pos) ' base type
123                 Dim depth%
124
125                 If type.IsInheritsFrom(parm.ParameterType, False, depth) Then
126                     If depth < depthMin Then
127                         depthMin = depth
128                         target = m
129                     End If
130                 End If
131             Next
132
133             If target Is Nothing Then
134                 If Runtime.Numerics.IndexOf(Type.GetTypeCode(type)) > -1 Then
135                     For Each m As MethodInfo In methods
136                         Dim parm As ParameterInfo = m.GetParameters(pos) ' base type
137                         If Runtime.Numerics.IndexOf(Type.GetTypeCode(parm.ParameterType)) > -1 Then
138                             Return m
139                         End If
140                     Next
141                 End If
142             End If
143
144             Return target
145         End Function
146
147         ''' <summary>
148         ''' 参数在右边
149         ''' </summary>
150         ''' <param name="self"></param>
151         ''' <param name="obj"></param>
152         ''' <param name="result"></param>
153         ''' <returns></returns>
154         ''' 
155         <MethodImpl(MethodImplOptions.AggressiveInlining)>
156         Public Function InvokeSelfLeft(self As Object, obj As ObjectByRef result As ObjectAs Boolean
157             Return __invokeInternal(self, obj, 0, result)
158         End Function
159
160         Private Function __invokeInternal(self As Object, obj As Object, pos%, ByRef result As ObjectAs Boolean
161             Dim type As Type = obj.GetType
162             Dim target As MethodInfo = Match(type, If(pos = 1, 0, 1))
163
164             If Not target Is Nothing Then
165                 If pos = 0 Then
166                     result = target.Invoke(Nothing, {self, obj})
167                 Else
168                     result = target.Invoke(Nothing, {obj, self})
169                 End If
170             Else
171                 Return False
172             End If
173
174             Return True
175         End Function
176
177         ''' <summary>
178         ''' 参数在左边
179         ''' </summary>
180         ''' <param name="obj"></param>
181         ''' <param name="self"></param>
182         ''' <param name="result"></param>
183         ''' <returns></returns>
184         ''' 
185         <MethodImpl(MethodImplOptions.AggressiveInlining)>
186         Public Function InvokeSelfRight(obj As Object, self As ObjectByRef result As ObjectAs Boolean
187             Return __invokeInternal(self, obj, 1, result)
188         End Function
189
190         Public Shared Function CreateOperator(methods As MethodInfo()) As BinaryOperator
191             If methods.IsNullOrEmpty Then
192                 Return Nothing
193             Else
194                 Return New BinaryOperator([overloads]:=methods)
195             End If
196         End Function
197     End Class
198 End Namespace