diff --git a/LINQ/LINQ/Interpreter/Executable.vb b/LINQ/LINQ/Interpreter/Executable.vb deleted file mode 100644 index b2adbb7..0000000 --- a/LINQ/LINQ/Interpreter/Executable.vb +++ /dev/null @@ -1,6 +0,0 @@ -Namespace Interpreter - - Public Class Executable - - End Class -End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/ExecutableContext.vb b/LINQ/LINQ/Interpreter/ExecutableContext.vb new file mode 100644 index 0000000..5b6aa67 --- /dev/null +++ b/LINQ/LINQ/Interpreter/ExecutableContext.vb @@ -0,0 +1,11 @@ +Imports LINQ.Runtime + +Namespace Interpreter + + Public Class ExecutableContext + + Public Property env As Environment + Public Property throwError As Boolean = True + + End Class +End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/Expressions/ArrayExpression.vb b/LINQ/LINQ/Interpreter/Expressions/ArrayExpression.vb index 17b09e3..6b5b463 100644 --- a/LINQ/LINQ/Interpreter/Expressions/ArrayExpression.vb +++ b/LINQ/LINQ/Interpreter/Expressions/ArrayExpression.vb @@ -10,11 +10,11 @@ Namespace Interpreter.Expressions Me.seq = seq.ToArray End Sub - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Dim list As New List(Of Object) For Each item In seq - list.Add(item.Exec(env)) + list.Add(item.Exec(context)) Next Return list.ToArray diff --git a/LINQ/LINQ/Interpreter/Expressions/BinaryExpression.vb b/LINQ/LINQ/Interpreter/Expressions/BinaryExpression.vb index 46efb93..dcec6f3 100644 --- a/LINQ/LINQ/Interpreter/Expressions/BinaryExpression.vb +++ b/LINQ/LINQ/Interpreter/Expressions/BinaryExpression.vb @@ -23,9 +23,9 @@ Namespace Interpreter.Expressions Me.op = op End Sub - Public Overrides Function Exec(env As Environment) As Object - Dim x As Object = left.Exec(env) - Dim y As Object = right.Exec(env) + Public Overrides Function Exec(context As ExecutableContext) As Object + Dim x As Object = left.Exec(context) + Dim y As Object = right.Exec(context) Select Case op Case "+" : Return x + y diff --git a/LINQ/LINQ/Interpreter/Expressions/Expression.vb b/LINQ/LINQ/Interpreter/Expressions/Expression.vb index c396026..d2f4148 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Expression.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Expression.vb @@ -6,11 +6,11 @@ Namespace Interpreter.Expressions Public ReadOnly Property name As String Get - Return MyClass.GetType.Name + Return MyClass.GetType.Name.ToLower End Get End Property - Public MustOverride Function Exec(env As Environment) As Object + Public MustOverride Function Exec(context As ExecutableContext) As Object End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/Expressions/FuncEval.vb b/LINQ/LINQ/Interpreter/Expressions/FuncEval.vb index 63078ae..6c036ca 100644 --- a/LINQ/LINQ/Interpreter/Expressions/FuncEval.vb +++ b/LINQ/LINQ/Interpreter/Expressions/FuncEval.vb @@ -7,15 +7,20 @@ Namespace Interpreter.Expressions Public Property func As Expression Public Property parameters As Expression() - Public Overrides Function Exec(env As Environment) As Object - Dim invoke As Object = func.Exec(env) + Sub New(func As Expression, parameters As IEnumerable(Of Expression)) + Me.func = func + Me.parameters = parameters.ToArray + End Sub + + Public Overrides Function Exec(context As ExecutableContext) As Object + Dim invoke As Object = func.Exec(New ExecutableContext With {.env = context.env, .throwError = False}) If invoke Is Nothing Then Throw New NullReferenceException ElseIf TypeOf invoke Is String Then - invoke = env.FindInvoke(invoke) + invoke = context.env.FindInvoke(invoke) ElseIf TypeOf invoke Is SymbolReference Then - invoke = env.FindInvoke(DirectCast(invoke, SymbolReference).symbolName) + invoke = context.env.FindInvoke(DirectCast(invoke, SymbolReference).symbolName) Else Throw New NotImplementedException End If @@ -23,12 +28,16 @@ Namespace Interpreter.Expressions Dim args As New List(Of Object) For Each item In parameters - args.Add(item.Exec(env)) + args.Add(item.Exec(context)) Next Dim result As Object = invoke(args.ToArray) Return result End Function + + Public Overrides Function ToString() As String + Return $"{func}({parameters.JoinBy(", ")})" + End Function End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb index 1b222e9..620efe8 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb @@ -18,19 +18,21 @@ Namespace Interpreter.Expressions Me.key = FixLiteral(key) End Sub - Public Overrides Function Exec(env As Environment) As Object - Return key.Exec(env) + Public Overrides Function Exec(context As ExecutableContext) As Object + Return key.Exec(context) End Function - Private Function GetOrderKey(obj As JavaScriptObject, env As Environment) As Object + Private Function GetOrderKey(obj As JavaScriptObject, context As ExecutableContext) As Object + Dim env As Environment = context.env + For Each key As String In obj env.FindSymbol(key).value = obj(key) Next - Return Exec(env) + Return Exec(context) End Function - Public Overrides Function Exec(result As IEnumerable(Of JavaScriptObject), env As Environment) As IEnumerable(Of JavaScriptObject) + Public Overrides Function Exec(result As IEnumerable(Of JavaScriptObject), context As ExecutableContext) As IEnumerable(Of JavaScriptObject) Dim raw As JavaScriptObject() = result.ToArray Dim keys As Object() Dim i As Integer() @@ -42,7 +44,7 @@ Namespace Interpreter.Expressions Else keys = raw _ .Select(Function(obj) - Return GetOrderKey(obj, env) + Return GetOrderKey(obj, context) End Function) _ .ToArray End If diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/PipelineKeyword.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/PipelineKeyword.vb index eb2929e..b854cf0 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/PipelineKeyword.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/PipelineKeyword.vb @@ -5,7 +5,7 @@ Namespace Interpreter.Expressions Public MustInherit Class PipelineKeyword : Inherits KeywordExpression - Public MustOverride Overloads Function Exec(result As IEnumerable(Of JavaScriptObject), env As Environment) As IEnumerable(Of JavaScriptObject) + Public MustOverride Overloads Function Exec(result As IEnumerable(Of JavaScriptObject), context As ExecutableContext) As IEnumerable(Of JavaScriptObject) ''' ''' 将字符串常量表示转换为变量引用 diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/TakeItems.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/TakeItems.vb index d0c882e..c21784b 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/TakeItems.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/TakeItems.vb @@ -18,12 +18,12 @@ Namespace Interpreter.Expressions Me.n = n End Sub - Public Overrides Function Exec(result As IEnumerable(Of JavaScriptObject), env As Environment) As IEnumerable(Of JavaScriptObject) - Return result.Take(count:=CInt(Exec(env))) + Public Overrides Function Exec(result As IEnumerable(Of JavaScriptObject), context As ExecutableContext) As IEnumerable(Of JavaScriptObject) + Return result.Take(count:=CInt(Exec(context))) End Function - Public Overrides Function Exec(env As Environment) As Object - Return n.Exec(env) + Public Overrides Function Exec(context As ExecutableContext) As Object + Return n.Exec(context) End Function End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/OutputProjection.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/OutputProjection.vb index 4891012..0cce916 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/OutputProjection.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/OutputProjection.vb @@ -18,11 +18,11 @@ Namespace Interpreter.Expressions Me.fields = fields.ToArray End Sub - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Dim obj As New JavaScriptObject For Each field In fields - obj(field.Name) = field.Value.Exec(env) + obj(field.Name) = field.Value.Exec(context) Next Return obj diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/SymbolDeclare.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/SymbolDeclare.vb index 7c8a9d3..cb58bae 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/SymbolDeclare.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/SymbolDeclare.vb @@ -13,7 +13,7 @@ Namespace Interpreter.Expressions End Get End Property - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Throw New NotImplementedException() End Function diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/WhereFilter.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/WhereFilter.vb index 3f895f4..f132411 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/WhereFilter.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/WhereFilter.vb @@ -16,8 +16,8 @@ Namespace Interpreter.Expressions Me.filter = filter End Sub - Public Overrides Function Exec(env As Environment) As Object - Return filter.Exec(env) + Public Overrides Function Exec(context As ExecutableContext) As Object + Return filter.Exec(context) End Function Public Overrides Function ToString() As String diff --git a/LINQ/LINQ/Interpreter/Expressions/Literals.vb b/LINQ/LINQ/Interpreter/Expressions/Literals.vb index 2bd8a30..55b54f0 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Literals.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Literals.vb @@ -30,7 +30,7 @@ Namespace Interpreter.Expressions End Select End Sub - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Return value End Function diff --git a/LINQ/LINQ/Interpreter/Expressions/MemberReference.vb b/LINQ/LINQ/Interpreter/Expressions/MemberReference.vb index 857447f..a11161d 100644 --- a/LINQ/LINQ/Interpreter/Expressions/MemberReference.vb +++ b/LINQ/LINQ/Interpreter/Expressions/MemberReference.vb @@ -21,8 +21,8 @@ Namespace Interpreter.Expressions End If End Sub - Public Overrides Function Exec(env As Environment) As Object - Dim symbol As Object = Me.symbol.Exec(env) + Public Overrides Function Exec(context As ExecutableContext) As Object + Dim symbol As Object = Me.symbol.Exec(context) If symbol Is Nothing Then Throw New NullReferenceException diff --git a/LINQ/LINQ/Interpreter/Expressions/SymbolReference.vb b/LINQ/LINQ/Interpreter/Expressions/SymbolReference.vb index e7943be..6e516d5 100644 --- a/LINQ/LINQ/Interpreter/Expressions/SymbolReference.vb +++ b/LINQ/LINQ/Interpreter/Expressions/SymbolReference.vb @@ -10,11 +10,15 @@ Namespace Interpreter.Expressions Me.symbolName = name End Sub - Public Overrides Function Exec(env As Environment) As Object - Dim symbol As Symbol = env.FindSymbol(symbolName) + Public Overrides Function Exec(context As ExecutableContext) As Object + Dim symbol As Symbol = context.env.FindSymbol(symbolName) If symbol Is Nothing Then - Throw New MissingPrimaryKeyException(symbolName) + If context.throwError Then + Throw New MissingPrimaryKeyException(symbolName) + Else + Return Nothing + End If Else Return symbol.value End If diff --git a/LINQ/LINQ/Interpreter/Query/AggregateExpression.vb b/LINQ/LINQ/Interpreter/Query/AggregateExpression.vb index 41db12e..0b8dcd9 100644 --- a/LINQ/LINQ/Interpreter/Query/AggregateExpression.vb +++ b/LINQ/LINQ/Interpreter/Query/AggregateExpression.vb @@ -12,7 +12,7 @@ Namespace Interpreter.Query Call MyBase.New(symbol, sequence, exec) End Sub - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Throw New NotImplementedException() End Function End Class diff --git a/LINQ/LINQ/Interpreter/Query/DataSoruce.vb b/LINQ/LINQ/Interpreter/Query/DataSoruce.vb index 14a1598..9796ba3 100644 --- a/LINQ/LINQ/Interpreter/Query/DataSoruce.vb +++ b/LINQ/LINQ/Interpreter/Query/DataSoruce.vb @@ -16,11 +16,13 @@ Namespace Interpreter.Query Public MustOverride Function PopulatesData() As IEnumerable(Of Object) - Public Shared Function CreateDataSet(query As QueryExpression, env As Environment) As DataSet + Public Shared Function CreateDataSet(query As QueryExpression, context As ExecutableContext) As DataSet + Dim env As Environment = context.env + If query.IsURISource Then Return New URIIteratorDriver(query, query.GetSeqValue(Nothing), env) Else - Dim seqVal As Object = query.GetSeqValue(env) + Dim seqVal As Object = query.GetSeqValue(context) If TypeOf seqVal Is String Then Return New URIIteratorDriver(query, seqVal, env) diff --git a/LINQ/LINQ/Interpreter/Query/ProjectionExpression.vb b/LINQ/LINQ/Interpreter/Query/ProjectionExpression.vb index e672300..025e1ce 100644 --- a/LINQ/LINQ/Interpreter/Query/ProjectionExpression.vb +++ b/LINQ/LINQ/Interpreter/Query/ProjectionExpression.vb @@ -15,9 +15,10 @@ Namespace Interpreter.Query .ToArray End Sub - Public Function RunOptionPipeline(output As IEnumerable(Of JavaScriptObject), env As Environment) As IEnumerable(Of JavaScriptObject) + Public Function RunOptionPipeline(output As IEnumerable(Of JavaScriptObject), context As ExecutableContext) As IEnumerable(Of JavaScriptObject) Dim raw As JavaScriptObject() = output.ToArray Dim allNames As String() = raw(Scan0).GetNames + Dim env As Environment = context.env For Each name As String In allNames If Not env.HasSymbol(name) Then @@ -26,7 +27,7 @@ Namespace Interpreter.Query Next For Each line As PipelineKeyword In pipeline - raw = line.Exec(raw, env).ToArray + raw = line.Exec(raw, context).ToArray Next Return raw @@ -52,20 +53,24 @@ Namespace Interpreter.Query ''' ''' ''' - ''' + ''' ''' ''' array of ''' - Public Overrides Function Exec(env As Environment) As Object + Public Overrides Function Exec(context As ExecutableContext) As Object Dim projections As New List(Of JavaScriptObject) - Dim closure As New Environment(parent:=env) + Dim env As Environment = context.env + Dim closure As New ExecutableContext With { + .env = New Environment(parent:=env), + .throwError = context.throwError + } Dim skipVal As Boolean - Dim dataset As DataSet = GetDataSet(env) + Dim dataset As DataSet = GetDataSet(context) - Call closure.AddSymbol(symbol.symbolName, symbol.type) + Call closure.env.AddSymbol(symbol.symbolName, symbol.type) For Each item As Object In dataset.PopulatesData() - closure.FindSymbol(symbol.symbolName).value = item + closure.env.FindSymbol(symbol.symbolName).value = item For Each line As Expression In executeQueue If TypeOf line Is WhereFilter Then @@ -82,7 +87,7 @@ Namespace Interpreter.Query End If Next - Return opt.RunOptionPipeline(projections, env).ToArray + Return opt.RunOptionPipeline(projections, context).ToArray End Function End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Interpreter/Query/Query.vb b/LINQ/LINQ/Interpreter/Query/Query.vb index 3fac0d4..456ad91 100644 --- a/LINQ/LINQ/Interpreter/Query/Query.vb +++ b/LINQ/LINQ/Interpreter/Query/Query.vb @@ -22,12 +22,12 @@ Namespace Interpreter.Query Me.executeQueue = execQueue.ToArray End Sub - Public Function GetSeqValue(env As Environment) As Object - Return sequence.Exec(env) + Public Function GetSeqValue(context As ExecutableContext) As Object + Return sequence.Exec(context) End Function - Protected Function GetDataSet(env As Environment) As DataSet - Return DataSet.CreateDataSet(Me, env) + Protected Function GetDataSet(context As ExecutableContext) As DataSet + Return DataSet.CreateDataSet(Me, context) End Function End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/LINQ.vbproj b/LINQ/LINQ/LINQ.vbproj index 32889ca..b68a562 100644 --- a/LINQ/LINQ/LINQ.vbproj +++ b/LINQ/LINQ/LINQ.vbproj @@ -155,7 +155,7 @@ - + diff --git a/LINQ/LINQ/Program.vb b/LINQ/LINQ/Program.vb index 5cfdcb4..6dca65b 100644 --- a/LINQ/LINQ/Program.vb +++ b/LINQ/LINQ/Program.vb @@ -1,4 +1,5 @@ -Imports LINQ.Interpreter.Query +Imports LINQ.Interpreter +Imports LINQ.Interpreter.Query Imports LINQ.Runtime Imports LINQ.Script Imports Microsoft.VisualBasic.ApplicationServices.Terminal @@ -16,7 +17,7 @@ Module Program Dim tokens = LINQ.Language.GetTokens(file.ReadAllText).ToArray Dim query As ProjectionExpression = tokens.PopulateQueryExpression Dim env As New GlobalEnvironment(New Registry) - Dim result As JavaScriptObject() = query.Exec(env) + Dim result As JavaScriptObject() = query.Exec(New ExecutableContext With {.env = env, .throwError = True}) Dim table As DataFrame = result.CreateTableDataSet Dim text As String()() = table _ .csv _ diff --git a/LINQ/LINQ/Runtime/Environment.vb b/LINQ/LINQ/Runtime/Environment.vb index 52e7f35..b9ce6d0 100644 --- a/LINQ/LINQ/Runtime/Environment.vb +++ b/LINQ/LINQ/Runtime/Environment.vb @@ -58,7 +58,7 @@ Namespace Runtime ElseIf Not parent Is Nothing Then Return parent.FindSymbol(name) Else - Throw New MissingPrimaryKeyException(name) + Return Nothing End If End Function diff --git a/LINQ/LINQ/Runtime/Math.vb b/LINQ/LINQ/Runtime/Math.vb index 92d1b32..0bb7d5f 100644 --- a/LINQ/LINQ/Runtime/Math.vb +++ b/LINQ/LINQ/Runtime/Math.vb @@ -7,6 +7,7 @@ Namespace Runtime Public Shared ReadOnly abs As New Callable(AddressOf stdnum.Abs) Public Shared ReadOnly min As New Callable(AddressOf stdnum.Min) Public Shared ReadOnly max As New Callable(AddressOf stdnum.Max) + Public Shared ReadOnly pow As New Callable(AddressOf stdnum.Pow) End Class End Namespace \ No newline at end of file diff --git a/LINQ/LINQ/Script/SyntaxImplements.vb b/LINQ/LINQ/Script/SyntaxImplements.vb index a18b99f..69d775d 100644 --- a/LINQ/LINQ/Script/SyntaxImplements.vb +++ b/LINQ/LINQ/Script/SyntaxImplements.vb @@ -168,6 +168,11 @@ Namespace Script End If End Function + + Private Function IsClosure(tokenList As Token()) As Boolean + Return tokenList(Scan0).name = Tokens.Open AndAlso tokenList.Last.name = Tokens.Close + End Function + Public Function ParseExpression(tokenList As Token()) As Expression If tokenList.Length = 1 Then @@ -189,6 +194,12 @@ Namespace Script .Take(tokenList.Length - 2) _ .ToArray End If + ElseIf blocks.Length = 2 Then + Dim name As Expression = ParseExpression(blocks(Scan0)) + + If TypeOf name Is SymbolReference AndAlso blocks(1).IsClosure Then + Return New FuncEval(name, blocks(1).Skip(1).Take(blocks(1).Length - 2).GetParameters) + End If End If Return tokenList.ParseBinary diff --git a/LINQ/LINQ/test/Program.vb b/LINQ/LINQ/test/Program.vb index 5dc357b..f7d99aa 100644 --- a/LINQ/LINQ/test/Program.vb +++ b/LINQ/LINQ/test/Program.vb @@ -3,6 +3,7 @@ Imports LINQ.Runtime Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel Imports LINQ.Interpreter.Query Imports Microsoft.VisualBasic.My.JavaScript +Imports LINQ.Interpreter Public Module Program @@ -27,7 +28,7 @@ order by y Dim query As ProjectionExpression = tokens.PopulateQueryExpression Dim env As New GlobalEnvironment(New Registry, New NamedValue(Of Object)("y", 1)) - Dim result As JavaScriptObject() = query.Exec(env) + Dim result As JavaScriptObject() = query.Exec(New ExecutableContext With {.env = env, .throwError = True}) Dim table = result.CreateTableDataSet Pause()