R-sharp/R#/Runtime/Extensions.vb

295 lines
10 KiB
VB.net
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::d8a8ccfcf096c8ab989915f58587c46e, R#\Runtime\Extensions.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program 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 3 of the License, or
' (at your option) any later version.
'
' This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Code Statistics:
' Total Lines: 239
' Code Lines: 150 (62.76%)
' Comment Lines: 56 (23.43%)
' - Xml Docs: 78.57%
'
' Blank Lines: 33 (13.81%)
' File Size: 8.82 KB
' Module Extensions
'
' Function: isCallable, MeasureArrayElementType, MeasureRealElementType, MeasureVectorType, MeasureVectorTypes
' Push, strictOption, TryCatch, verboseOption
'
'
' /********************************************************************************/
#End Region
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
Imports Microsoft.VisualBasic.Emit.Delegates
Imports SMRUCC.Rsharp.Interpreter.ExecuteEngine.ExpressionSymbols.Closure
Imports SMRUCC.Rsharp.Runtime.Components.Interface
Imports SMRUCC.Rsharp.Runtime.Internal.[Object]
Imports vbObject = SMRUCC.Rsharp.Runtime.Internal.Object.vbObject
Namespace Runtime
<HideModuleName> Public Module Extensions
''' <summary>
''' If exception happens, then this function will catch
''' the exceptin object and then returns the error.
''' </summary>
''' <param name="runScript"></param>
''' <returns></returns>
Public Function TryCatch(runScript As Func(Of Object), debug As Boolean) As Object
If debug Then
Return runScript()
Else
Try
Return runScript()
Catch ex As Exception
Return ex
End Try
End If
End Function
''' <summary>
''' 这个函数只会尝试第一个不为空的元素的类型
''' </summary>
''' <param name="array"></param>
''' <returns></returns>
Public Function MeasureArrayElementType(array As Array) As Type
Dim x As Object
Dim arrayType As Type = array.GetType
If arrayType.HasElementType AndAlso Not arrayType.GetElementType Is GetType(Object) Then
Return arrayType.GetElementType
End If
For i As Integer = 0 To array.Length - 1
x = array.GetValue(i)
If x IsNot Nothing AndAlso
x IsNot invalidObject.value AndAlso
x IsNot GetType(Void) Then
Return x.GetType
End If
Next
Return GetType(Void)
End Function
Public Function MeasureVectorTypes(array As Array, Optional unique As Boolean = True, Optional excludeInterfaceOrAbstract As Boolean = False) As IEnumerable(Of Type)
Dim arrayType As Type = array.GetType
Dim x As Object
Dim types As New List(Of Type)
If array.Length = 0 Then
Return New Type() {}
End If
Dim elType As Type = arrayType.GetElementType
If arrayType.HasElementType AndAlso Not elType Is GetType(Object) Then
If excludeInterfaceOrAbstract Then
If Not (elType.IsAbstract OrElse elType.IsInterface) Then
Return New Type() {elType}
End If
Else
Return New Type() {elType}
End If
End If
For i As Integer = 0 To array.Length - 1
x = array.GetValue(i)
If x IsNot Nothing AndAlso
x IsNot invalidObject.value AndAlso
x IsNot GetType(Void) Then
arrayType = x.GetType
If arrayType Is GetType(vbObject) Then
arrayType = DirectCast(x, vbObject).target.GetType
End If
types.Add(arrayType)
End If
Next
If unique Then
Return types.Distinct
Else
Return types
End If
End Function
Public Function MeasureVectorType(types As Type()) As Type
If types.Length = 0 Then
Return GetType(Object)
End If
If types.Length = 1 OrElse types.Distinct.Count = 1 Then
Return types(Scan0)
End If
Dim tg = types _
.GroupBy(Function(t) t.FullName) _
.OrderByDescending(Function(k) k.Count) _
.ToArray
' 都是相同类型
If tg.Length = 1 Then
Return tg(Scan0).First
End If
' 按照类型缩放原则进行类型的选取
Dim allTypes As Type() = tg.Select(Function(g) g.First).ToArray
' 排序之后一般sub type会排在最开始
' base type会排在最后
allTypes = allTypes _
.Sort(Function(a, b)
If a.IsInheritsFrom(b) Then
Return -1
Else
' 按照full name排序
Return a.FullName.CompareTo(b.FullName)
End If
End Function) _
.ToArray
' 如果最开始的类型可以继承自最末尾的类型
' 则返回最末尾的类型
If allTypes(Scan0).IsInheritsFrom(allTypes.Last) Then
Return allTypes.Last
ElseIf allTypes.Any(Function(t) t Is GetType(Double)) AndAlso
allTypes.All(Function(t) DataFramework.IsNumericType(t)) Then
Return GetType(Double)
ElseIf allTypes.All(Function(t) DataFramework.IsIntegerType(t)) Then
Return GetType(Long)
Else
' 反之说明类型间没有继承关系即互不兼容则返回object类型
Return GetType(Object)
End If
End Function
''' <summary>
''' 这个会遵循类型缩放的原则返回最大的类型
''' </summary>
''' <param name="array"></param>
''' <returns>
''' if all of the element in the given <paramref name="array"/> is nothing
''' then function returns the <paramref name="defaultType"/> value
''' </returns>
Public Function MeasureRealElementType(array As Array, Optional defaultType As Type = Nothing) As Type
Dim types As Type() = MeasureVectorTypes(array, unique:=False).ToArray
If types.Length = 0 Then
Return If(defaultType, GetType(Void))
Else
Return MeasureVectorType(types)
End If
End Function
''' <summary>
''' test target object is a <see cref="RFunction"/> or not
''' </summary>
''' <param name="x"></param>
''' <returns></returns>
Public Function isCallable(x As Object) As Boolean
If x Is Nothing Then
Return False
ElseIf x.GetType.ImplementInterface(Of RFunction) Then
Return True
Else
Return False
End If
End Function
''' <summary>
''' push runtime function parameters
''' </summary>
''' <param name="env"></param>
''' <param name="parameters"></param>
''' <returns></returns>
<Extension>
Friend Function Push(env As Environment, parameters As IEnumerable(Of DeclareNewSymbol)) As Environment
For Each symbol As DeclareNewSymbol In parameters
For Each name As String In symbol.names
Call env.Push(name, Nothing, [readonly]:=False)
Next
Next
Return env
End Function
''' <summary>
''' get strict options value
''' </summary>
''' <param name="env">The runtime context</param>
''' <param name="opt"></param>
''' <returns></returns>
<Extension>
Public Function strictOption(env As Environment, Optional opt As Boolean? = Nothing) As Boolean
If opt Is Nothing Then
Return env.globalEnvironment.options.strict
Else
Return opt
End If
End Function
''' <summary>
''' get verbose options value
''' </summary>
''' <param name="env">
''' The runtime context
''' </param>
''' <param name="opt"></param>
''' <returns></returns>
<Extension>
Public Function verboseOption(env As Environment, Optional opt As Boolean? = Nothing) As Boolean
' is the parameter value is nothing, then
' use the config from the runtime configuration
If opt Is Nothing Then
Return env.globalEnvironment.options.verbose
Else
' else the user input parameter value always
' overrides the runtime configuration
Return opt
End If
End Function
End Module
End Namespace