How To: Serialize your DataTable to Silverlight using WCF service

by Vladimir Enchev | Comments 35

Did you know that you can serialize any DataTable to Silverlight easily from your custom WCF service in very few lines of code?

[OperationContract]
public IEnumerable<Dictionary<string, object>> GetData()
{
    var table = YourDataTable;

    var columns = table.Columns.Cast<DataColumn>();

    return table.AsEnumerable().Select(r => columns.Select(c =>
                         new { Column = c.ColumnName, Value = r[c] })
                     .ToDictionary(i => i.Column, i => i.Value != DBNull.Value ? i.Value : null));
}

 

I’ve made small update for my lightweight DataTable for Silverlight and now you can create the table directly from IEnumerable<Dictionary<string, object>>:

namespace Telerik.Data
{
    public class DataTable : IEnumerable
    {
        public DataTable(IEnumerable<Dictionary<string, object>> source)
        {
            ...
}
    }
}

Now you can use all these to serialize any DataTable with unknown number of columns and types to the Silverlight client and bind desired control:

XAML
<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView">
    <Grid x:Name="LayoutRoot">
        <telerik:RadGridView x:Name="RadGridView1" />
    </Grid>
</UserControl>



C#

using System.Windows.Controls;
using SilverlightApplication1.ServiceReference1;
using Telerik.Data;

namespace SilverlightApplication1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            var client = new MyServiceClient();
            client.GetDataCompleted += (s,e) => 
            {
                RadGridView1.ItemsSource = new DataTable(e.Result);
            };

            client.GetDataAsync("SELECT CustomerID, CompanyName, ContactName, City, Country, Address, Fax FROM Customers");
        }
    }
}


The result - fully functional dynamic DataGrid and DataTable:
 image

Enjoy!

 

,
Senior Technical Architect

35 Comments

Aurélien Dubosson
Hi Vlad,

In your former post Lightweight Data Table for your Silverlight applications, you say we can use Dynamic Linq.

If I understand I can on server side create my own datatable comprising all data of a database and return it with a webservice to the client.

Have you got an example how to use Dynamic Linq with a datatable ? With that can we create our own query to display data into Rad GridView ? 

Aurélien Dubosson
Hi Vlad,

In your former post Lightweight Data Table for your Silverlight applications, you say we can use Dynamic Linq.

If I understand I can on server side create my own datatable comprising all data of a database and return it with a webservice to the client.

Have you got an example how to use Dynamic Linq with a datatable ? With that can we create our own query to display data into Rad GridView ? 

Vlad
Hi Aurélien,

Indeed in the first version of my DataTable I've used Dynamic LINQ library however we've changed this and now you do not need Dynamic LINQ.
The idea of this post was to show how to convert and serialize any server-side DataTable to IEnumerable<Dictionary<string, object>> and how to populate our own DataTable client-side with this data.

Vlad
Aurélien Dubosson
Hi Vlad,

I try to change the sql query just with SELECT CustomerID FROM Customers I always have the same result with all columns.

I'm beginner with C# I don't understand the following sentence, what means (s,e)  => ?
client.GetDataCompleted += (s,e) => 

Thanks for your previous response.

Aurélien
Varsha Motwani
Please tell me how to save the data after changes in the grid back to db
Vlad
You will need additional method for your service where you can post desired changes - for example the grid Items collection.
Ali Wieckowicz

Love this solution!

 

Maybe you have some suggestions.  I have a stored procedure that returns an undefined number of tables and I’m trying to wrap my head around how I might be able to modify this solution in such a way to allow the service to return multiple tables as single response.   Can I serialize the dataset or table collection in a similar way, or do I have to build an object?

Thanks,

Ali W

Kevin McBrearty
I love this solution and have been using it in a project that I am developing.  I have a couple of questions though. 

1.  I am currently trying to use this with a RadChart and define a ChartSortDescriptor.  I get an error message stating at least one object must implement IComparable.  I believe that this doesn't work because the dictionary class doesn't implement IComparable but we also don't have the SortedDictionary class available to us.  Are you aware of any way to get this to work?

2.  The Web Service that I am using is written in VB.Net.  Do you know how to convert the following line to VB so that I can simplify how I am sending the data from the web service to the silverlight client?

 

 

return table.AsEnumerable().Select(r => columns.Select(c =>

 

 

 

new { Column = c.ColumnName, Value = r[c] })

 

.ToDictionary(i => i.Column, i => i.Value !=

 

DBNull.Value ? i.Value : null));

 

Kevin McBrearty
I as able to rework the code for the Web Service to vb.NET.  The code is below for anyone else who might need it.

    Public Function GetData(ByVal Query As String) As IEnumerable(Of Dictionary(Of String, Object)) Implements IEKService.GetData  
        Dim table As DataTable = GetDataTable(query)  
        Dim columns = table.Columns.Cast(Of DataColumn)()  
 
        Return table.AsEnumerable.Select(Function(r) columns.Select(Function(c) New With { _  
              .Column = c.ColumnName, _  
              .Value = r(c) _  
        }).ToDictionary(Function(i) i.Column, Function(i) If(i.Value Is DBNull.Value, Nothing, i.Value)))  
    End Function 

Also I had to make a slight modification to the constructor of the class to not throw an error when the first value of a column is null.  I am sure there is more elegant way to code this but it works.

        public DataTable(IEnumerable<Dictionary<string, object>> source)  
        {  
            if (source != null)  
            {  
                var firstItem = source.FirstOrDefault();  
 
                if (firstItem != null)  
                {  
                    foreach (var key in firstItem)  
                    {  
                        if (key.Value == null)  
                        {  
                            Columns.Add(new DataColumn() { ColumnName = key.Key, DataType = typeof(string) });  
                        }  
                        else  
                        {  
                            Columns.Add(new DataColumn() { ColumnName = key.Key, DataType = key.Value.GetType() });  
                        }                          
                    }  
 
                    foreach (var item in source)  
                    {  
                        var row = new DataRow();  
 
                        foreach (var key in item)  
                        {  
                            row[key.Key] = key.Value;  
                        }  
                        Rows.Add(row);  
                    }  
                }  
            }  
        } 

I am still looking at a way to get the sorting for the RadChart to work when using this Datatable.
Jim
Anybody know how to get this C# to work in VB?  I have everything else working. 

            var client = new MyServiceClient(); 
            client.GetDataCompleted += (s,e) =>  
            { 
                RadGridView1.ItemsSource = new DataTable(e.Result); 
            }; 
 

 Tried adding an event handler, but can't cast the e.result to a datatable.

    Dim client = New dynamicDataClient 
        AddHandler client.GetDataCompleted, AddressOf dynamicDataCompleted 
 
.... 
 
    Private Sub dynamicDataCompleted(ByVal sender As Object, ByVal e As GetDataCompletedEventArgs) 
 
        dataGrid.ItemsSource = New DataTable(e.results) 
    End Sub 
 
Atilla
Hi, dear Vlad

my SQL query 20 columns and 12 rows record but not load DataGrid.. Database records return, but not load Datagrid.. I don't understand? Please help me.

Thans Atilla.
Sam
I can't get the return statement to compile in VB.net.  This is what I am using (copied from above), but I am getting an overload resolution failed error.

Return table.AsEnumerable.Select(Function(r) columns.Select(Function(c) New With { _
              .Column = c.ColumnName, _
              .Value = r(c) _
        }).ToDictionary(Function(i) i.Column, Function(i) If(i.Value Is DBNull.Value, Nothing, i.Value)))
Vlad
 Here is the VB.NET version of the service:
Public Class MyService 
        <OperationContract> 
        Public Function GetData(ByVal query As StringAs IEnumerable(Of Dictionary(Of StringObject)) 
            Dim table = GetDataTable(query) 
 
            Dim columns = table.Columns.Cast(Of DataColumn)() 
 
            Return table.AsEnumerable().Select(Function(r) columns.Select(Function(c) New With {Key .Column = c.ColumnName, Key .Value = r(c)}).ToDictionary(Function(i) i.Column, Function(i)If(i.Value IsNot DBNull.Value, i.Value, Nothing))) 
        End Function 
 
        Public Function GetDataTable(ByVal query As StringAs DataTable 
            Dim connString = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString 
            Dim conn = New SqlConnection(connString) 
            Dim adapter = New SqlDataAdapter() 
            adapter.SelectCommand = New SqlCommand(query, conn) 
 
            Dim table = New DataTable() 
 
            conn.Open() 
            Try 
                adapter.Fill(table) 
            Finally 
                conn.Close() 
            End Try 
 
            Return table 
        End Function 
    End Class 
Sam
Sorry to be so annoying, but now I am having some issues on the client side converting the client side data table to vb.net.  I am using your example in the Lightweight data table for Silverlight.  Have you converted that anywhere?
Thanks,
Sam
Sam Bronchetti
Vlad,

In your latest serialization application, when I convert Dynamic.cs to VB.NET, there are a lot of compiler issues.  It also affects other portions of my application (like app.xaml won't compile any more).  Any thoughts?
Sam Bronchetti
1     Private queryable As IQueryable = Nothing 
2         Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator  
3             If queryable Is Nothing Then  
4                 Dim type = ClassFactory.Instance.GetDynamicClass(Me.Columns.[Select](Function(c) New DynamicProperty(c.ColumnName, c.DataType)))  
5                 Dim propertyInfos = type.GetProperties().ToList()  
6  
7                 Dim mylist = DirectCast(Activator.CreateInstance(GetType(List(Of )).MakeGenericType(type)), IList)  
8                 For Each row In Me.Rows  
9                     Dim item = Activator.CreateInstance(type)  
10                     propertyInfos.ForEach(Function(p) p.SetValue(item, row(p.Name), Nothing))  
11                     mylist.Add(item)  
12                 Next  
13  
14                 queryable = mylist.AsQueryable()  
15             End If  
16  
17             Return queryable.GetEnumerator()  
18         End Function 
I have converted just about all of the application.  The error I am getting now is on line 10 above.  The error I am getting is "Expression does not produce a value" (compiler error). I have the rest of DataTable.cs and Dynamic.cs converted to VB.  Any help on that last lambda expression would be greatly appreciated.
Hıncal
Hi Vlad,

I think there is a small problem with your DataTable in VS2010. I'm trying to use it to bind RadChart, but if I bind a date column in DateTime type then axis don't autostepping labels and everyting mixes. If I use OADate as double then everything works fine but tooltip formatting. So I stucked.. You may see my posts in telerik forums:

http://www.telerik.com/community/forums/silverlight/chart/radchart-axisx-label-autostep-misfunctionality.aspx
http://www.telerik.com/community/forums/silverlight/chart/oadate-support-in-tooltips.aspx

Although in VS2008 with DateTime type works flawlessly..
rc
Hi,

I tried the code and it generally works. but when it is already returning a large set (1400 rows with about 10 columns), it gives out an error.
Sam
RC,

I had something similar occur, but it is not an issue with the RadGridView or Vlad's Datatable, it is with the web service you might be calling.  In the web.config, I had to add something that looked like the following:
        <behaviors> 
            <serviceBehaviors> 
                <behavior name="slPartnerCare.Web.Service1Behavior">  
                    <serviceMetadata httpGetEnabled="true"/>  
                    <serviceDebug includeExceptionDetailInFaults="true"/>  
                    <dataContractSerializer maxItemsInObjectGraph="2147483646"/>  
                </behavior> 
            </serviceBehaviors> 
        </behaviors> 
 
The key was the dataContractSerializer.
Sam
''Copyright (C) Microsoft Corporation.  All rights reserved.  
 
Imports System.Collections.Generic  
Imports System.Text  
Imports System.Linq  
Imports System.Linq.Expressions  
Imports System.Reflection  
Imports System.Reflection.Emit  
Imports System.Threading  
Imports System.Dynamic  
Imports System.Runtime.CompilerServices  
 
Namespace SQLWiz.Dynamic  
    Module DynamicQueryable  
        Sub New()  
        End Sub  
        <Extension()> _  
        Public Function Where(Of T)(ByVal source As IQueryable(Of T), ByVal predicate As String, ByVal ParamArray values As Object()) As IQueryable(Of T)  
            Return DirectCast(Where(DirectCast(source, IQueryable), predicate, values), IQueryable(Of T))  
        End Function  
 
        <Extension()> _  
        Public Function Where(ByVal source As IQueryable, ByVal predicate As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If predicate Is Nothing Then  
                Throw New ArgumentNullException("predicate")  
            End If  
            Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, GetType(Boolean), predicate, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Where", New Type() {source.ElementType}, source.Expression, Expression.Quote(lambda)))  
        End Function  
 
        <Extension()> _  
        Public Function [Select](ByVal source As IQueryable, ByVal selector As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If selector Is Nothing Then  
                Throw New ArgumentNullException("selector")  
            End If  
            Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, selector, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Select", New Type() {source.ElementType, lambda.Body.Type}, source.Expression, Expression.Quote(lambda)))  
        End Function  
 
        <Extension()> _  
        Public Function OrderBy(Of T)(ByVal source As IQueryable(Of T), ByVal ordering As String, ByVal ParamArray values As Object()) As IQueryable(Of T)  
            Return DirectCast(OrderBy(DirectCast(source, IQueryable), ordering, values), IQueryable(Of T))  
        End Function  
 
        <Extension()> _  
        Public Function OrderBy(ByVal source As IQueryable, ByVal ordering As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If ordering Is Nothing Then  
                Throw New ArgumentNullException("ordering")  
            End If  
            Dim parameters As ParameterExpression() = New ParameterExpression() {Expression.Parameter(source.ElementType, "")}  
            Dim parser As New ExpressionParser(parameters, ordering, values)  
            Dim orderings As IEnumerable(Of DynamicOrdering) = parser.ParseOrdering()  
            Dim queryExpr As Expression = source.Expression  
            Dim methodAsc As String = "OrderBy" 
            Dim methodDesc As String = "OrderByDescending" 
            For Each o As DynamicOrdering In orderings  
                queryExpr = Expression.[Call](GetType(Queryable), If(o.Ascending, methodAsc, methodDesc), New Type() {source.ElementType, o.Selector.Type}, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)))  
                methodAsc = "ThenBy" 
                methodDesc = "ThenByDescending" 
            Next  
            Return source.Provider.CreateQuery(queryExpr)  
        End Function  
 
        <Extension()> _  
        Public Function Take(ByVal source As IQueryable, ByVal count As Integer) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Take", New Type() {source.ElementType}, source.Expression, Expression.Constant(count)))  
        End Function  
 
        <Extension()> _  
        Public Function Skip(ByVal source As IQueryable, ByVal count As Integer) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Skip", New Type() {source.ElementType}, source.Expression, Expression.Constant(count)))  
        End Function  
 
        <Extension()> _  
        Public Function GroupBy(ByVal source As IQueryable, ByVal keySelector As String, ByVal elementSelector As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If keySelector Is Nothing Then  
                Throw New ArgumentNullException("keySelector")  
            End If  
            If elementSelector Is Nothing Then  
                Throw New ArgumentNullException("elementSelector")  
            End If  
            Dim keyLambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, keySelector, values)  
            Dim elementLambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, elementSelector, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "GroupBy", New Type() {source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type}, source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)))  
        End Function  
 
        <Extension()> _  
        Public Function Any(ByVal source As IQueryable) As Boolean  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return CBool(source.Provider.Execute(Expression.[Call](GetType(Queryable), "Any", New Type() {source.ElementType}, source.Expression)))  
        End Function  
 
        <Extension()> _  
        Public Function Count(ByVal source As IQueryable) As Integer  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return CInt(source.Provider.Execute(Expression.[Call](GetType(Queryable), "Count", New Type() {source.ElementType}, source.Expression)))  
        End Function  
    End Module  
 
    Public MustInherit Class DynamicClass  
        Public Overrides Function ToString() As String  
            Dim props As PropertyInfo() = Me.[GetType]().GetProperties(BindingFlags.Instance Or BindingFlags.[Public])  
            Dim sb As New StringBuilder()  
            sb.Append("{")  
            For i As Integer = 0 To props.Length - 1  
                If i > 0 Then  
                    sb.Append(", ")  
                End If  
                sb.Append(props(i).Name)  
                sb.Append("=")  
                sb.Append(props(i).GetValue(Me, Nothing))  
            Next  
            sb.Append("}")  
            Return sb.ToString()  
        End Function  
    End Class  
 
    Public Class DynamicProperty  
        Private m_name As String  
        Private m_type As Type  
 
        Public Sub New(ByVal name As String, ByVal type As Type)  
            If name Is Nothing Then  
                Throw New ArgumentNullException("name")  
            End If  
            If type Is Nothing Then  
                Throw New ArgumentNullException("type")  
            End If  
            Me.m_name = name  
            Me.m_type = type  
        End Sub  
 
        Public ReadOnly Property Name() As String  
            Get  
                Return m_name  
            End Get  
        End Property  
 
        Public ReadOnly Property Type() As Type  
            Get  
                Return m_type  
            End Get  
        End Property  
    End Class  
 
    Module DynamicExpression  
        Sub New()  
        End Sub  
        Public Function Parse(ByVal resultType As Type, ByVal expression As String, ByVal ParamArray values As Object()) As Expression  
            Dim parser As New ExpressionParser(Nothing, expression, values)  
            Return parser.Parse(resultType)  
        End Function  
 
        Public Function ParseLambda(ByVal itType As Type, ByVal resultType As Type, ByVal expression__1 As String, ByVal ParamArray values As Object()) As LambdaExpression  
            Return ParseLambda(New ParameterExpression() {Expression.Parameter(itType, "")}, resultType, expression__1, values)  
        End Function  
 
        Public Function ParseLambda(ByVal parameters As ParameterExpression(), ByVal resultType As Type, ByVal expression__1 As String, ByVal ParamArray values As Object()) As LambdaExpression  
            Dim parser As New ExpressionParser(parameters, expression__1, values)  
            Return Expression.Lambda(parser.Parse(resultType), parameters)  
        End Function  
 
        Public Function ParseLambda(Of T, S)(ByVal expression As String, ByVal ParamArray values As Object()) As Expression(Of Func(Of T, S))  
            Return DirectCast(ParseLambda(GetType(T), GetType(S), expression, values), Expression(Of Func(Of T, S)))  
        End Function  
 
        Public Function CreateClass(ByVal ParamArray properties As DynamicProperty()) As Type  
            Return ClassFactory.Instance.GetDynamicClass(properties)  
        End Function  
 
        Public Function CreateClass(ByVal properties As IEnumerable(Of DynamicProperty)) As Type  
            Return ClassFactory.Instance.GetDynamicClass(properties)  
        End Function  
    End Module  
 
    Friend Class DynamicOrdering  
        Public Selector As Expression  
        Public Ascending As Boolean  
    End Class  
 
    Friend Class Signature  
        Implements IEquatable(Of Signature)  
        Public properties As DynamicProperty()  
        Public hashCode As Integer  
 
        Public Sub New(ByVal properties As IEnumerable(Of DynamicProperty))  
            Me.properties = properties.ToArray()  
            hashCode = 0 
            For Each p As DynamicProperty In properties  
                hashCodehashCode = hashCode Xor p.Name.GetHashCode() Xor p.Type.GetHashCode()  
            Next  
        End Sub  
 
        Public Overrides Function GetHashCode() As Integer  
            Return hashCode  
        End Function  
 
        Public Overrides Function Equals(ByVal obj As Object) As Boolean  
            Return If(TypeOf obj Is Signature, Equals(DirectCast(obj, Signature)), False)  
        End Function  
 
        Public Overloads Function Equals(ByVal other As Signature) As Boolean Implements IEquatable(Of Signature).Equals  
            If properties.Length <> other.properties.Length Then  
                Return False  
            End If  
            For i As Integer = 0 To properties.Length - 1  
                If properties(i).Name <> other.properties(i).Name OrElse properties(i).Type IsNot other.properties(i).Type Then  
                    Return False  
                End If  
            Next  
            Return True  
        End Function  
    End Class  
 
    Friend Class ClassFactory  
        Public Shared ReadOnly Instance As New ClassFactory()  
 
        Shared Sub New()  
        End Sub  
        ' Trigger lazy initialization of static fields  
        Private [module] As ModuleBuilder  
        Private classes As Dictionary(Of Signature, Type)  
        Private classCount As Integer  
 
        Private Sub New()  
            Dim name As New AssemblyName("DynamicClasses")  
            Dim assembly As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run)  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                New ReflectionPermission(PermissionState.Unrestricted).Assert()  
#End If  
            Try  
                [module] = assembly.DefineDynamicModule("Module")  
            Finally  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                PermissionSet.RevertAssert()  
#End If  
            End Try  
            classes = New Dictionary(Of Signature, Type)()  
        End Sub  
 
        Public Function GetDynamicClass(ByVal properties As IEnumerable(Of DynamicProperty)) As Type  
            Try  
                Dim signature As New Signature(properties)  
                Dim type As Type  
                If Not classes.TryGetValue(signature, type) Then  
                    type = CreateDynamicClass(signature.properties)  
                    classes.Add(signature, type)  
                End If  
                Return type  
            Finally  
            End Try  
        End Function  
 
        Private Function CreateDynamicClass(ByVal properties As DynamicProperty()) As Type  
            Try  
                Dim typeName As String = "DynamicClass" & (classCount + 1)  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                    New ReflectionPermission(PermissionState.Unrestricted).Assert()  
#End If  
                Try  
                    Dim tb As TypeBuilder = Me.[module].DefineType(typeName, TypeAttributes.[Class] Or TypeAttributes.[Public], GetType(DynamicClass))  
                    Dim fields As FieldInfo() = GenerateProperties(tb, properties)  
                    GenerateEquals(tb, fields)  
                    GenerateGetHashCode(tb, fields)  
                    Dim result As Type = tb.CreateType()  
                    classCount += 1  
                    Return result  
                Finally  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                    PermissionSet.RevertAssert()  
#End If  
                End Try  
            Finally  
            End Try  
        End Function  
 
        Private Function GenerateProperties(ByVal tb As TypeBuilder, ByVal properties As DynamicProperty()) As FieldInfo()  
            Dim fields As FieldInfo() = New FieldBuilder(properties.Length - 1) {}  
            For i As Integer = 0 To properties.Length - 1  
                Dim dp As DynamicProperty = properties(i)  
                Dim fb As FieldBuilder = tb.DefineField("_" & dp.Name, dp.Type, FieldAttributes.[Private])  
                Dim pb As PropertyBuilder = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, Nothing)  
                Dim mbGet As MethodBuilder = tb.DefineMethod("get_" & dp.Name, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, dp.Type, Type.EmptyTypes)  
                Dim genGet As ILGenerator = mbGet.GetILGenerator()  
                genGet.Emit(OpCodes.Ldarg_0)  
                genGet.Emit(OpCodes.Ldfld, fb)  
                genGet.Emit(OpCodes.Ret)  
                Dim mbSet As MethodBuilder = tb.DefineMethod("set_" & dp.Name, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, New Type() {dp.Type})  
                Dim genSet As ILGenerator = mbSet.GetILGenerator()  
                genSet.Emit(OpCodes.Ldarg_0)  
                genSet.Emit(OpCodes.Ldarg_1)  
                genSet.Emit(OpCodes.Stfld, fb)  
                genSet.Emit(OpCodes.Ret)  
                pb.SetGetMethod(mbGet)  
                pb.SetSetMethod(mbSet)  
                fields(i) = fb  
            Next  
            Return fields  
        End Function  
 
        Private Sub GenerateEquals(ByVal tb As TypeBuilder, ByVal fields As FieldInfo())  
            Dim mb As MethodBuilder = tb.DefineMethod("Equals", MethodAttributes.[Public] Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig, GetType(Boolean), New Type() {GetType(Object)})  
            Dim gen As ILGenerator = mb.GetILGenerator()  
            Dim other As LocalBuilder = gen.DeclareLocal(tb)  
            Dim [next] As Label = gen.DefineLabel()  
            gen.Emit(OpCodes.Ldarg_1)  
            gen.Emit(OpCodes.Isinst, tb)  
            gen.Emit(OpCodes.Stloc, other)  
            gen.Emit(OpCodes.Ldloc, other)  
            gen.Emit(OpCodes.Brtrue_S, [next])  
            gen.Emit(OpCodes.Ldc_I4_0)  
            gen.Emit(OpCodes.Ret)  
            gen.MarkLabel([next])  
            For Each field As FieldInfo In fields  
                Dim ft As Type = field.FieldType  
                Dim ct As Type = GetType(EqualityComparer(Of )).MakeGenericType(ft)  
                [next] = gen.DefineLabel()  
                gen.EmitCall(OpCodes.[Call], ct.GetMethod("get_Default"), Nothing)  
                gen.Emit(OpCodes.Ldarg_0)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.Emit(OpCodes.Ldloc, other)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", New Type() {ft, ft}), Nothing)  
                gen.Emit(OpCodes.Brtrue_S, [next])  
                gen.Emit(OpCodes.Ldc_I4_0)  
                gen.Emit(OpCodes.Ret)  
                gen.MarkLabel([next])  
            Next  
            gen.Emit(OpCodes.Ldc_I4_1)  
            gen.Emit(OpCodes.Ret)  
        End Sub  
 
        Private Sub GenerateGetHashCode(ByVal tb As TypeBuilder, ByVal fields As FieldInfo())  
            Dim mb As MethodBuilder = tb.DefineMethod("GetHashCode", MethodAttributes.[Public] Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig, GetType(Integer), Type.EmptyTypes)  
            Dim gen As ILGenerator = mb.GetILGenerator()  
            gen.Emit(OpCodes.Ldc_I4_0)  
            For Each field As FieldInfo In fields  
                Dim ft As Type = field.FieldType  
                Dim ct As Type = GetType(EqualityComparer(Of )).MakeGenericType(ft)  
                gen.EmitCall(OpCodes.[Call], ct.GetMethod("get_Default"), Nothing)  
                gen.Emit(OpCodes.Ldarg_0)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", New Type() {ft}), Nothing)  
                gen.Emit(OpCodes.[Xor])  
            Next  
            gen.Emit(OpCodes.Ret)  
        End Sub  
    End Class  
 
    Public NotInheritable Class ParseException  
        Inherits Exception  
        Private m_position As Integer  
 
        Public Sub New(ByVal message As String, ByVal position As Integer)  
            MyBase.New(message)  
            Me.m_position = position  
        End Sub  
 
        Public ReadOnly Property Position() As Integer  
            Get  
                Return m_position  
            End Get  
        End Property  
 
        Public Overrides Function ToString() As String  
            Return String.Format(Res.ParseExceptionFormat, Message, m_position)  
        End Function  
    End Class  
 
    Friend Class ExpressionParser  
        Private Structure myToken  
            Public id As TokenId  
            Public text As String  
            Public pos As Integer  
        End Structure  
 
        Private Enum TokenId  
            Unknown  
            [End]  
            Identifier  
            StringLiteral  
            IntegerLiteral  
            RealLiteral  
            Exclamation  
            Percent  
            Amphersand  
            OpenParen  
            CloseParen  
            Asterisk  
            Plus  
            Comma  
            Minus  
            Dot  
            Slash  
            Colon  
            LessThan  
            Equal  
            GreaterThan  
            Question  
            OpenBracket  
            CloseBracket  
            Bar  
            ExclamationEqual  
            DoubleAmphersand  
            LessThanEqual  
            LessGreater  
            DoubleEqual  
            GreaterThanEqual  
            DoubleBar  
        End Enum  
 
        Private Interface ILogicalSignatures  
            Sub F(ByVal x As Boolean, ByVal y As Boolean)  
            Sub F(ByVal x As Global.System.Nullable(Of Boolean), ByVal y As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IArithmeticSignatures  
            Sub F(ByVal x As Integer, ByVal y As Integer)  
            Sub F(ByVal x As UInteger, ByVal y As UInteger)  
            Sub F(ByVal x As Long, ByVal y As Long)  
            Sub F(ByVal x As ULong, ByVal y As ULong)  
            Sub F(ByVal x As Single, ByVal y As Single)  
            Sub F(ByVal x As Double, ByVal y As Double)  
            Sub F(ByVal x As Decimal, ByVal y As Decimal)  
            Sub F(ByVal x As Global.System.Nullable(Of Integer), ByVal y As Global.System.Nullable(Of Integer))  
            Sub F(ByVal x As Global.System.Nullable(Of UInteger), ByVal y As Global.System.Nullable(Of UInteger))  
            Sub F(ByVal x As Global.System.Nullable(Of Long), ByVal y As Global.System.Nullable(Of Long))  
            Sub F(ByVal x As Global.System.Nullable(Of ULong), ByVal y As Global.System.Nullable(Of ULong))  
            Sub F(ByVal x As Global.System.Nullable(Of Single), ByVal y As Global.System.Nullable(Of Single))  
            Sub F(ByVal x As Global.System.Nullable(Of Double), ByVal y As Global.System.Nullable(Of Double))  
            Sub F(ByVal x As Global.System.Nullable(Of Decimal), ByVal y As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Private Interface IRelationalSignatures  
            Inherits IArithmeticSignatures  
            Overloads Sub F(ByVal x As String, ByVal y As String)  
            Overloads Sub F(ByVal x As Char, ByVal y As Char)  
            Overloads Sub F(ByVal x As DateTime, ByVal y As DateTime)  
            Overloads Sub F(ByVal x As TimeSpan, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of Char), ByVal y As Global.System.Nullable(Of Char))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of DateTime))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of TimeSpan), ByVal y As Global.System.Nullable(Of TimeSpan))  
        End Interface  
 
        Private Interface IEqualitySignatures  
            Inherits IRelationalSignatures  
            Overloads Sub F(ByVal x As Boolean, ByVal y As Boolean)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of Boolean), ByVal y As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IAddSignatures  
            Inherits IArithmeticSignatures  
            Overloads Sub F(ByVal x As DateTime, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As TimeSpan, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of TimeSpan))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of TimeSpan), ByVal y As Global.System.Nullable(Of TimeSpan))  
        End Interface  
 
        Private Interface ISubtractSignatures  
            Inherits IAddSignatures  
            Overloads Sub F(ByVal x As DateTime, ByVal y As DateTime)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of DateTime))  
        End Interface  
 
        Private Interface INegationSignatures  
            Sub F(ByVal x As Integer)  
            Sub F(ByVal x As Long)  
            Sub F(ByVal x As Single)  
            Sub F(ByVal x As Double)  
            Sub F(ByVal x As Decimal)  
            Sub F(ByVal x As Global.System.Nullable(Of Integer))  
            Sub F(ByVal x As Global.System.Nullable(Of Long))  
            Sub F(ByVal x As Global.System.Nullable(Of Single))  
            Sub F(ByVal x As Global.System.Nullable(Of Double))  
            Sub F(ByVal x As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Private Interface INotSignatures  
            Sub F(ByVal x As Boolean)  
            Sub F(ByVal x As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IEnumerableSignatures  
            Sub Where(ByVal predicate As Boolean)  
            Sub Any()  
            Sub Any(ByVal predicate As Boolean)  
            Sub All(ByVal predicate As Boolean)  
            Sub Count()  
            Sub Count(ByVal predicate As Boolean)  
            Sub Min(ByVal selector As Object)  
            Sub Max(ByVal selector As Object)  
            Sub Sum(ByVal selector As Integer)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Integer))  
            Sub Sum(ByVal selector As Long)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Long))  
            Sub Sum(ByVal selector As Single)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Single))  
            Sub Sum(ByVal selector As Double)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Double))  
            Sub Sum(ByVal selector As Decimal)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Decimal))  
            Sub Average(ByVal selector As Integer)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Integer))  
            Sub Average(ByVal selector As Long)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Long))  
            Sub Average(ByVal selector As Single)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Single))  
            Sub Average(ByVal selector As Double)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Double))  
            Sub Average(ByVal selector As Decimal)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Shared ReadOnly predefinedTypes As Type() = {GetType([Object]), GetType([Boolean]), GetType([Char]), GetType([String]), GetType([SByte]), GetType([Byte]), _  
         GetType(Int16), GetType(UInt16), GetType(Int32), GetType(UInt32), GetType(Int64), GetType(UInt64), _  
         GetType([Single]), GetType([Double]), GetType([Decimal]), GetType(DateTime), GetType(TimeSpan), GetType(Guid), _  
         GetType(Math), GetType(Convert)}  
 
        Shared ReadOnly trueLiteral As ExpressionExpression = Expression.Constant(True)  
        Shared ReadOnly falseLiteral As ExpressionExpression = Expression.Constant(False)  
        Shared ReadOnly nullLiteral As ExpressionExpression = Expression.Constant(Nothing)  
 
        Shared ReadOnly keywordIt As String = "it" 
        Shared ReadOnly keywordIif As String = "iif" 
        Shared ReadOnly keywordNew As String = "new" 
 
        Shared keywords As Dictionary(Of String, Object)  
 
        Private symbols As Dictionary(Of String, Object)  
        Private externals As IDictionary(Of String, Object)  
        Private literals As Dictionary(Of Expression, String)  
        Private it As ParameterExpression  
        Private text As String  
        Private textPos As Integer  
        Private textLen As Integer  
        Private ch As Char  
        Private varToken As myToken  
 
        Public Sub New(ByVal parameters As ParameterExpression(), ByVal expression As String, ByVal values As Object())  
            If expression Is Nothing Then  
                Throw New ArgumentNullException("expression")  
            End If  
            If keywords Is Nothing Then  
                keywords = CreateKeywords()  
            End If  
            symbols = New Dictionary(Of String, Object)(StringComparer.OrdinalIgnoreCase)  
            literals = New Dictionary(Of Expression, String)()  
            If parameters IsNot Nothing Then  
                ProcessParameters(parameters)  
            End If  
            If values IsNot Nothing Then  
                ProcessValues(values)  
            End If  
            text = expression 
            texttextLen = text.Length  
            SetTextPos(0)  
            NextToken()  
        End Sub  
 
        Private Sub ProcessParameters(ByVal parameters As ParameterExpression())  
            For Each pe As ParameterExpression In parameters  
                If Not [String].IsNullOrEmpty(pe.Name) Then  
                    AddSymbol(pe.Name, pe)  
                End If  
            Next  
            If parameters.Length = 1 AndAlso [String].IsNullOrEmpty(parameters(0).Name) Then  
                it = parameters(0)  
            End If  
        End Sub  
 
        Private Sub ProcessValues(ByVal values As Object())  
            For i As Integer = 0 To values.Length - 1  
                Dim value As Object = values(i)  
                If i = values.Length - 1 AndAlso TypeOf value Is IDictionary(Of String, Object) Then  
                    externals = DirectCast(value, IDictionary(Of String, Object))  
                Else  
                    AddSymbol("@" & i.ToString(Globalization.CultureInfo.InvariantCulture), value)  
                End If  
            Next  
        End Sub  
 
        Private Sub AddSymbol(ByVal name As String, ByVal value As Object)  
            If symbols.ContainsKey(name) Then  
                Throw ParseError(Res.DuplicateIdentifier, name)  
            End If  
            symbols.Add(name, value)  
        End Sub  
 
        Public Function Parse(ByVal resultType As Type) As Expression  
            Dim exprPos As Integer = varToken.pos  
            Dim expr As Expression = ParseExpression()  
            If resultType IsNot Nothing Then  
                If (InlineAssignHelper(expr, PromoteExpression(expr, resultType, True))) Is Nothing Then  
                    Throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType))  
                End If  
            End If  
            ValidateToken(TokenId.[End], Res.SyntaxError)  
            Return expr  
        End Function  
 
        '#Pragma warning disable 0219  
        Public Function ParseOrdering() As IEnumerable(Of DynamicOrdering)  
            Dim orderings As New List(Of DynamicOrdering)()  
            While True  
                Dim expr As Expression = ParseExpression()  
                Dim ascending As Boolean = True 
                If TokenIdentifierIs("asc") OrElse TokenIdentifierIs("ascending") Then  
                    NextToken()  
                ElseIf TokenIdentifierIs("desc") OrElse TokenIdentifierIs("descending") Then  
                    NextToken()  
                    ascending = False 
                End If  
                orderings.Add(New DynamicOrdering() With { _  
                  .Selector = expr, _  
                  .Ascending = ascending _  
                })  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            ValidateToken(TokenId.[End], Res.SyntaxError)  
            Return orderings  
        End Function  
        '#Pragma warning restore 0219  
 
        ' ?: operator  
        Private Function ParseExpression() As Expression  
            Dim errorPos As Integer = varToken.pos  
            Dim expr As Expression = ParseLogicalOr()  
            If varToken.id = TokenId.Question Then  
                NextToken()  
                Dim expr1 As Expression = ParseExpression()  
                ValidateToken(TokenId.Colon, Res.ColonExpected)  
                NextToken()  
                Dim expr2 As Expression = ParseExpression()  
                expr = GenerateConditional(expr, expr1, expr2, errorPos)  
            End If  
            Return expr  
        End Function  
 
        ' ||, or operator  
        Private Function ParseLogicalOr() As Expression  
            Dim left As Expression = ParseLogicalAnd()  
            While varToken.id = TokenId.DoubleBar OrElse TokenIdentifierIs("or")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseLogicalAnd()  
                CheckAndPromoteOperands(GetType(ILogicalSignatures), op.text, left, right, op.pos)  
                left = Expression.[OrElse](left, right)  
            End While  
            Return left  
        End Function  
 
        ' &&, and operator  
        Private Function ParseLogicalAnd() As Expression  
            Dim left As Expression = ParseComparison()  
            While varToken.id = TokenId.DoubleAmphersand OrElse TokenIdentifierIs("and")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseComparison()  
                CheckAndPromoteOperands(GetType(ILogicalSignatures), op.text, left, right, op.pos)  
                left = Expression.[AndAlso](left, right)  
            End While  
            Return left  
        End Function  
 
        ' =, ==, !=, <>, >>=, <<= operators  
        Private Function ParseComparison() As Expression  
            Dim left As Expression = ParseAdditive()  
            While varToken.id = TokenId.Equal OrElse varToken.id = TokenId.DoubleEqual OrElse varToken.id = TokenId.ExclamationEqual OrElse varToken.id = TokenId.LessGreater OrElse varToken.id = TokenId.GreaterThan OrElse varToken.id = TokenId.GreaterThanEqual OrElse varToken.id = TokenId.LessThan OrElse varToken.id = TokenId.LessThanEqual  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseAdditive()  
                Dim isEquality As Boolean = op.id = TokenId.Equal OrElse op.id = TokenId.DoubleEqual OrElse op.id = TokenId.ExclamationEqual OrElse op.id = TokenId.LessGreater  
                If isEquality AndAlso Not left.Type.IsValueType AndAlso Not right.Type.IsValueType Then  
                    If Not left.Type.Equals(right.Type) Then  
                        If left.Type.IsAssignableFrom(right.Type) Then  
                            right = Expression.Convert(right, left.Type)  
                        ElseIf right.Type.IsAssignableFrom(left.Type) Then  
                            left = Expression.Convert(left, right.Type)  
                        Else  
                            Throw IncompatibleOperandsError(op.text, left, right, op.pos)  
                        End If  
                    End If  
                ElseIf IsEnumType(left.Type) OrElse IsEnumType(right.Type) Then  
                    If Not left.Type.Equals(right.Type) Then  
                        Dim e As Expression  
                        If (InlineAssignHelper(e, PromoteExpression(right, left.Type, True))) IsNot Nothing Then  
                            right = e 
                        ElseIf (InlineAssignHelper(e, PromoteExpression(left, right.Type, True))) IsNot Nothing Then  
                            left = e  
                        Else  
                            Throw IncompatibleOperandsError(op.text, left, right, op.pos)  
                        End If  
                    End If  
                Else  
                    CheckAndPromoteOperands(If(isEquality, GetType(IEqualitySignatures), GetType(IRelationalSignatures)), op.text, left, right, op.pos)  
                End If  
                Select Case op.id  
                    Case TokenId.Equal, TokenId.DoubleEqual  
                        left = GenerateEqual(left, right)  
                        Exit Select  
                    Case TokenId.ExclamationEqual, TokenId.LessGreater  
                        left = GenerateNotEqual(left, right)  
                        Exit Select  
                    Case TokenId.GreaterThan  
                        left = GenerateGreaterThan(left, right)  
                        Exit Select  
                    Case TokenId.GreaterThanEqual  
                        left = GenerateGreaterThanEqual(left, right)  
                        Exit Select  
                    Case TokenId.LessThan  
                        left = GenerateLessThan(left, right)  
                        Exit Select  
                    Case TokenId.LessThanEqual  
                        left = GenerateLessThanEqual(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' +, -, & operators  
        Private Function ParseAdditive() As Expression  
            Dim left As Expression = ParseMultiplicative()  
            While varToken.id = TokenId.Plus OrElse varToken.id = TokenId.Minus OrElse varToken.id = TokenId.Amphersand  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseMultiplicative()  
                Select Case op.id  
                    Case TokenId.Plus  
                        If left.Type.Equals(GetType(String)) OrElse right.Type.Equals(GetType(String)) Then  
                            left = GenerateStringConcat(left, right)  
                            Exit Select  
                        End If  
                        CheckAndPromoteOperands(GetType(IAddSignatures), op.text, left, right, op.pos)  
                        left = GenerateAdd(left, right)  
                        Exit Select  
                    Case TokenId.Minus  
                        CheckAndPromoteOperands(GetType(ISubtractSignatures), op.text, left, right, op.pos)  
                        left = GenerateSubtract(left, right)  
                        Exit Select  
                    Case TokenId.Amphersand  
                        left = GenerateStringConcat(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' *, /, %, mod operators  
        Private Function ParseMultiplicative() As Expression  
            Dim left As Expression = ParseUnary()  
            While varToken.id = TokenId.Asterisk OrElse varToken.id = TokenId.Slash OrElse varToken.id = TokenId.Percent OrElse TokenIdentifierIs("mod")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseUnary()  
                CheckAndPromoteOperands(GetType(IArithmeticSignatures), op.text, left, right, op.pos)  
                Select Case op.id  
                    Case TokenId.Asterisk  
                        left = Expression.Multiply(left, right)  
                        Exit Select  
                    Case TokenId.Slash  
                        left = Expression.Divide(left, right)  
                        Exit Select  
                    Case TokenId.Percent, TokenId.Identifier  
                        left = Expression.Modulo(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' -, !, not unary operators  
        Private Function ParseUnary() As Expression  
            If varToken.id = TokenId.Minus OrElse varToken.id = TokenId.Exclamation OrElse TokenIdentifierIs("not") Then  
                Dim op As myToken = varToken 
                NextToken()  
                If op.id = TokenId.Minus AndAlso (varToken.id = TokenId.IntegerLiteral OrElse varToken.id = TokenId.RealLiteral) Then  
                    varToken.text = "-" & varToken.text  
                    varToken.pos = op.pos  
                    Return ParsePrimary()  
                End If  
                Dim expr As Expression = ParseUnary()  
                If op.id = TokenId.Minus Then  
                    CheckAndPromoteOperand(GetType(INegationSignatures), op.text, expr, op.pos)  
                    expr = Expression.Negate(expr)  
                Else  
                    CheckAndPromoteOperand(GetType(INotSignatures), op.text, expr, op.pos)  
                    expr = Expression.[Not](expr)  
                End If  
                Return expr  
            End If  
            Return ParsePrimary()  
        End Function  
 
        Private Function ParsePrimary() As Expression  
            Dim expr As Expression = ParsePrimaryStart()  
            While True  
                If varToken.id = TokenId.Dot Then  
                    NextToken()  
                    expr = ParseMemberAccess(Nothing, expr)  
                ElseIf varToken.id = TokenId.OpenBracket Then  
                    expr = ParseElementAccess(expr)  
                Else  
                    Exit While  
                End If  
            End While  
            Return expr  
        End Function  
 
        Private Function ParsePrimaryStart() As Expression  
            Select Case varToken.id  
                Case TokenId.Identifier  
                    Return ParseIdentifier()  
                Case TokenId.StringLiteral  
                    Return ParseStringLiteral()  
                Case TokenId.IntegerLiteral  
                    Return ParseIntegerLiteral()  
                Case TokenId.RealLiteral  
                    Return ParseRealLiteral()  
                Case TokenId.OpenParen  
                    Return ParseParenExpression()  
                Case Else  
                    Throw ParseError(Res.ExpressionExpected)  
            End Select  
        End Function  
 
        Private Function ParseStringLiteral() As Expression  
            ValidateToken(TokenId.StringLiteral)  
            Dim quote As Char = varToken.text(0)  
            Dim s As String = varToken.text.Substring(1, varToken.text.Length - 2)  
            Dim start As Integer = 0 
            While True  
                Dim i As Integer = s.IndexOf(quote, start)  
                If i < 0 Then  
                    Exit While  
                End If  
                ss = s.Remove(i, 1)  
                start = i + 1  
            End While  
            If quote = "'"c Then  
                If s.Length <> 1 Then  
                    Throw ParseError(Res.InvalidCharacterLiteral)  
                End If  
                NextToken()  
                Return CreateLiteral(s(0), s)  
            End If  
            NextToken()  
            Return CreateLiteral(s, s)  
        End Function  
 
        Private Function ParseIntegerLiteral() As Expression  
            ValidateToken(TokenId.IntegerLiteral)  
            Dim text As String = varToken.text  
            If text(0) <> "-"c Then  
                Dim value As ULong  
                If Not UInt64.TryParse(text, value) Then  
                    Throw ParseError(Res.InvalidIntegerLiteral, text)  
                End If  
                NextToken()  
                If value <= CULng(Int32.MaxValue) Then  
                    Return CreateLiteral(CInt(value), text)  
                End If  
                If value <= CULng(UInt32.MaxValue) Then  
                    Return CreateLiteral(CUInt(value), text)  
                End If  
                If value <= CULng(Int64.MaxValue) Then  
                    Return CreateLiteral(CLng(value), text)  
                End If  
                Return CreateLiteral(value, text)  
            Else  
                Dim value As Long  
                If Not Int64.TryParse(text, value) Then  
                    Throw ParseError(Res.InvalidIntegerLiteral, text)  
                End If  
                NextToken()  
                If value >= Int32.MinValue AndAlso value <= Int32.MaxValue Then  
                    Return CreateLiteral(CInt(value), text)  
                End If  
                Return CreateLiteral(value, text)  
            End If  
        End Function  
 
        Private Function ParseRealLiteral() As Expression  
            ValidateToken(TokenId.RealLiteral)  
            Dim text As String = varToken.text  
            Dim value As Object = Nothing 
            Dim last As Char = text(text.Length - 1)  
            If last = "F"c OrElse last = "f"c Then  
                Dim f As Single  
                If [Single].TryParse(text.Substring(0, text.Length - 1), f) Then  
                    value = f 
                End If  
            Else  
                Dim d As Double  
                If [Double].TryParse(text, d) Then  
                    value = d 
                End If  
            End If  
            If value Is Nothing Then  
                Throw ParseError(Res.InvalidRealLiteral, text)  
            End If  
            NextToken()  
            Return CreateLiteral(value, text)  
        End Function  
 
        Private Function CreateLiteral(ByVal value As Object, ByVal text As String) As Expression  
            Dim expr As ConstantExpression = Expression.Constant(value)  
            literals.Add(expr, text)  
            Return expr  
        End Function  
 
        Private Function ParseParenExpression() As Expression  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim e As Expression = ParseExpression()  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected)  
            NextToken()  
            Return e  
        End Function  
 
        Private Function ParseIdentifier() As Expression  
            ValidateToken(TokenId.Identifier)  
            Dim value As Object  
            If keywords.TryGetValue(varToken.text, value) Then  
                If TypeOf value Is Type Then  
                    Return ParseTypeAccess(DirectCast(value, Type))  
                End If  
                If value Is DirectCast(keywordIt, Object) Then  
                    Return ParseIt()  
                End If  
                If value Is DirectCast(keywordIif, Object) Then  
                    Return ParseIif()  
                End If  
                If value Is DirectCast(keywordNew, Object) Then  
                    Return ParseNew()  
                End If  
                NextToken()  
                Return DirectCast(value, Expression)  
            End If  
            If symbols.TryGetValue(varToken.text, value) OrElse externals IsNot Nothing AndAlso externals.TryGetValue(varToken.text, value) Then  
                Dim expr As Expression = TryCast(value, Expression)  
                If expr Is Nothing Then  
                    expr = Expression.Constant(value)  
                Else  
                    Dim lambda As LambdaExpression = TryCast(expr, LambdaExpression)  
                    If lambda IsNot Nothing Then  
                        Return ParseLambdaInvocation(lambda)  
                    End If  
                End If  
                NextToken()  
                Return expr  
            End If  
            If it IsNot Nothing Then  
                Return ParseMemberAccess(Nothing, it)  
            End If  
            Throw ParseError(Res.UnknownIdentifier, varToken.text)  
        End Function  
 
        Private Function ParseIt() As Expression  
            If it Is Nothing Then  
                Throw ParseError(Res.NoItInScope)  
            End If  
            NextToken()  
            Return it  
        End Function  
 
        Private Function ParseIif() As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            Dim args As Expression() = ParseArgumentList()  
            If args.Length <> 3 Then  
                Throw ParseError(errorPos, Res.IifRequiresThreeArgs)  
            End If  
            Return GenerateConditional(args(0), args(1), args(2), errorPos)  
        End Function  
 
        Private Function GenerateConditional(ByVal test As Expression, ByVal expr1 As Expression, ByVal expr2 As Expression, ByVal errorPos As Integer) As Expression  
            If Not test.Type.Equals(GetType(Boolean)) Then  
                Throw ParseError(errorPos, Res.FirstExprMustBeBool)  
            End If  
            If Not expr1.Type.Equals(expr2.Type) Then  
                Dim expr1as2 As Expression = If(Not expr2.Equals(nullLiteral), PromoteExpression(expr1, expr2.Type, True), Nothing)  
                Dim expr2as1 As Expression = If(Not expr2.Equals(nullLiteral), PromoteExpression(expr2, expr1.Type, True), Nothing)  
                If expr1as2 IsNot Nothing AndAlso expr2as1 Is Nothing Then  
                    expr1 = expr1as2 
                ElseIf expr2as1 IsNot Nothing AndAlso expr1as2 Is Nothing Then  
                    expr2 = expr2as1 
                Else  
                    Dim type1 As String = If(Not expr2.Equals(nullLiteral), expr1.Type.Name, "null")  
                    Dim type2 As String = If(Not expr2.Equals(nullLiteral), expr2.Type.Name, "null")  
                    If expr1as2 IsNot Nothing AndAlso expr2as1 IsNot Nothing Then  
                        Throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2)  
                    End If  
                    Throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2)  
                End If  
            End If  
            Return Expression.Condition(test, expr1, expr2)  
        End Function  
 
        Private Function ParseNew() As Expression  
            NextToken()  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim properties As New List(Of DynamicProperty)()  
            Dim expressions As New List(Of Expression)()  
            While True  
                Dim exprPos As Integer = varToken.pos  
                Dim expr As Expression = ParseExpression()  
                Dim propName As String  
                If TokenIdentifierIs("as") Then  
                    NextToken()  
                    propName = GetIdentifier()  
                    NextToken()  
                Else  
                    Dim [me] As MemberExpression = TryCast(expr, MemberExpression)  
                    If [me] Is Nothing Then  
                        Throw ParseError(exprPos, Res.MissingAsClause)  
                    End If  
                    propName = [me].Member.Name  
                End If  
                expressions.Add(expr)  
                properties.Add(New DynamicProperty(propName, expr.Type))  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected)  
            NextToken()  
            Dim type As Type = DynamicExpression.CreateClass(properties)  
            Dim bindings As MemberBinding() = New MemberBinding(properties.Count - 1) {}  
            For i As Integer = 0 To bindings.Length - 1  
                bindings(i) = Expression.Bind(type.GetProperty(properties(i).Name), expressions(i))  
            Next  
            Return Expression.MemberInit(Expression.[New](type), bindings)  
        End Function  
 
        Private Function ParseLambdaInvocation(ByVal lambda As LambdaExpression) As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            Dim args As Expression() = ParseArgumentList()  
            Dim method As MethodBase  
            If FindMethod(lambda.Type, "Invoke", False, args, method) <> 1 Then  
                Throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda)  
            End If  
            Return Expression.Invoke(lambda, args)  
        End Function  
 
        Private Function ParseTypeAccess(ByVal type As Type) As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            If varToken.id = TokenId.Question Then  
                If Not type.IsValueType OrElse IsNullableType(type) Then  
                    Throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type))  
                End If  
                type = GetType(Nullable(Of )).MakeGenericType(type)  
                NextToken()  
            End If  
            If varToken.id = TokenId.OpenParen Then  
                Dim args As Expression() = ParseArgumentList()  
                Dim method As MethodBase  
                Select Case FindBestMethod(type.GetConstructors(), args, method)  
                    Case 0  
                        If args.Length = 1 Then  
                            Return GenerateConversion(args(0), type, errorPos)  
                        End If  
                        Throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type))  
                    Case 1  
                        Return Expression.[New](DirectCast(method, ConstructorInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type))  
                End Select  
            End If  
            ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected)  
            NextToken()  
            Return ParseMemberAccess(type, Nothing)  
        End Function  
 
        Private Function GenerateConversion(ByVal expr As Expression, ByVal type As Type, ByVal errorPos As Integer) As Expression  
            Dim exprType As Type = expr.Type  
            If exprType Is type Then  
                Return expr  
            End If  
            If exprType.IsValueType AndAlso type.IsValueType Then  
                If (IsNullableType(exprType) OrElse IsNullableType(type)) AndAlso GetNonNullableType(exprType) Is GetNonNullableType(type) Then  
                    Return Expression.Convert(expr, type)  
                End If  
                If (IsNumericType(exprType) OrElse IsEnumType(exprType)) AndAlso (IsNumericType(type)) OrElse IsEnumType(type) Then  
                    Return Expression.ConvertChecked(expr, type)  
                End If  
            End If  
            If exprType.IsAssignableFrom(type) OrElse type.IsAssignableFrom(exprType) OrElse exprType.IsInterface OrElse type.IsInterface Then  
                Return Expression.Convert(expr, type)  
            End If  
            Throw ParseError(errorPos, Res.CannotConvertValue, GetTypeName(exprType), GetTypeName(type))  
        End Function  
 
        Private Function ParseMemberAccess(ByVal type As Type, ByVal instance As Expression) As Expression  
            If instance IsNot Nothing Then  
                type = instance.Type  
            End If  
            Dim errorPos As Integer = varToken.pos  
            Dim id As String = GetIdentifier()  
            NextToken()  
            If varToken.id = TokenId.OpenParen Then  
                If instance IsNot Nothing AndAlso type IsNot GetType(String) Then  
                    Dim enumerableType As Type = FindGenericType(GetType(IEnumerable(Of )), type)  
                    If enumerableType IsNot Nothing Then  
                        Dim elementType As Type = enumerableType.GetGenericArguments()(0)  
                        Return ParseAggregate(instance, elementType, id, errorPos)  
                    End If  
                End If  
                Dim args As Expression() = ParseArgumentList()  
                Dim mb As MethodBase  
                Select Case FindMethod(type, id, instance Is Nothing, args, mb)  
                    Case 0  
                        Throw ParseError(errorPos, Res.NoApplicableMethod, id, GetTypeName(type))  
                    Case 1  
                        Dim method As MethodInfo = DirectCast(mb, MethodInfo)  
                        If Not IsPredefinedType(method.DeclaringType) Then  
                            Throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType))  
                        End If  
                        If method.ReturnType Is GetType(Void) Then  
                            Throw ParseError(errorPos, Res.MethodIsVoid, id, GetTypeName(method.DeclaringType))  
                        End If  
                        Return Expression.[Call](instance, DirectCast(method, MethodInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousMethodInvocation, id, GetTypeName(type))  
                End Select  
            Else  
                Dim member As MemberInfo = FindPropertyOrField(type, id, instance Is Nothing)  
                If member Is Nothing Then  
                    Throw ParseError(errorPos, Res.UnknownPropertyOrField, id, GetTypeName(type))  
                End If  
                Return If(TypeOf member Is PropertyInfo, Expression.[Property](instance, DirectCast(member, PropertyInfo)), Expression.Field(instance, DirectCast(member, FieldInfo)))  
            End If  
        End Function  
 
        Private Shared Function FindGenericType(ByVal generic As Type, ByVal type As Type) As Type  
            While type IsNot Nothing AndAlso type IsNot GetType(Object)  
                If type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is generic Then  
                    Return type  
                End If  
                If generic.IsInterface Then  
                    For Each intfType As Type In type.GetInterfaces()  
                        Dim found As Type = FindGenericType(generic, intfType)  
                        If found IsNot Nothing Then  
                            Return found  
                        End If  
                    Next  
                End If  
                typetype = type.BaseType  
            End While  
            Return Nothing  
        End Function  
 
        Private Function ParseAggregate(ByVal instance As Expression, ByVal elementType As Type, ByVal methodName As String, ByVal errorPos As Integer) As Expression  
            Dim outerIt As ParameterExpression = it 
            Dim innerIt As ParameterExpression = Expression.Parameter(elementType, "")  
            it = innerIt 
            Dim args As Expression() = ParseArgumentList()  
            it = outerIt 
            Dim signature As MethodBase  
            If FindMethod(GetType(IEnumerableSignatures), methodName, False, args, signature) <> 1 Then  
                Throw ParseError(errorPos, Res.NoApplicableAggregate, methodName)  
            End If  
            Dim typeArgs As Type()  
            If signature.Name = "Min" OrElse signature.Name = "Max" Then  
                typeArgs = New Type() {elementType, args(0).Type}  
            Else  
                typeArgs = New Type() {elementType}  
            End If  
            If args.Length = 0 Then  
                args = New Expression() {instance}  
            Else  
                args = New Expression() {instance, Expression.Lambda(args(0), innerIt)}  
            End If  
            Return Expression.[Call](GetType(Enumerable), signature.Name, typeArgs, args)  
        End Function  
 
        Private Function ParseArgumentList() As Expression()  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim args As Expression() = If(varToken.id <> TokenId.CloseParen, ParseArguments(), New Expression(-1) {})  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected)  
            NextToken()  
            Return args  
        End Function  
 
        Private Function ParseArguments() As Expression()  
            Dim argList As New List(Of Expression)()  
            While True  
                argList.Add(ParseExpression())  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            Return argList.ToArray()  
        End Function  
 
        Private Function ParseElementAccess(ByVal expr As Expression) As Expression  
            Dim errorPos As Integer = varToken.pos  
            ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected)  
            NextToken()  
            Dim args As Expression() = ParseArguments()  
            ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected)  
            NextToken()  
            If expr.Type.IsArray Then  
                If expr.Type.GetArrayRank() <> 1 OrElse args.Length <> 1 Then  
                    Throw ParseError(errorPos, Res.CannotIndexMultiDimArray)  
                End If  
                Dim index As Expression = PromoteExpression(args(0), GetType(Integer), True)  
                If index Is Nothing Then  
                    Throw ParseError(errorPos, Res.InvalidIndex)  
                End If  
                Return Expression.ArrayIndex(expr, index)  
            Else  
                Dim mb As MethodBase  
                Select Case FindIndexer(expr.Type, args, mb)  
                    Case 0  
                        Throw ParseError(errorPos, Res.NoApplicableIndexer, GetTypeName(expr.Type))  
                    Case 1  
                        Return Expression.[Call](expr, DirectCast(mb, MethodInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousIndexerInvocation, GetTypeName(expr.Type))  
                End Select  
            End If  
        End Function  
 
        Private Shared Function IsPredefinedType(ByVal type As Type) As Boolean  
            For Each t As Type In predefinedTypes  
                If t Is type Then  
                    Return True  
                End If  
            Next  
            Return False  
        End Function  
 
        Private Shared Function IsNullableType(ByVal type As Type) As Boolean  
            Return type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is GetType(Nullable(Of ))  
        End Function  
 
        Private Shared Function GetNonNullableType(ByVal type As Type) As Type  
            Return If(IsNullableType(type), type.GetGenericArguments()(0), type)  
        End Function  
 
        Private Shared Function GetTypeName(ByVal type As Type) As String  
            Dim baseType As Type = GetNonNullableType(type)  
            Dim s As String = baseType.Name  
            If type IsNot baseType Then  
                s += "?"c  
            End If  
            Return s  
        End Function  
 
        Private Shared Function IsNumericType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) <> 0  
        End Function  
 
        Private Shared Function IsSignedIntegralType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) = 2  
        End Function  
 
        Private Shared Function IsUnsignedIntegralType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) = 3  
        End Function  
 
        Private Shared Function GetNumericTypeKind(ByVal type__1 As Type) As Integer  
            type__1 = GetNonNullableType(type__1)  
            If type__1.IsEnum Then  
                Return 0  
            End If  
            Select Case Type.GetTypeCode(type__1)  
                Case TypeCode.[Char], TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                    Return 1  
                Case TypeCode.[SByte], TypeCode.Int16, TypeCode.Int32, TypeCode.Int64  
                    Return 2  
                Case TypeCode.[Byte], TypeCode.UInt16, TypeCode.UInt32, TypeCode.UInt64  
                    Return 3  
                Case Else  
                    Return 0  
            End Select  
        End Function  
 
        Private Shared Function IsEnumType(ByVal type As Type) As Boolean  
            Return GetNonNullableType(type).IsEnum  
        End Function  
 
        Private Sub CheckAndPromoteOperand(ByVal signatures As Type, ByVal opName As String, ByRef expr As Expression, ByVal errorPos As Integer)  
            Dim args As Expression() = New Expression() {expr}  
            Dim method As MethodBase  
            If FindMethod(signatures, "F", False, args, method) <> 1 Then  
                Throw ParseError(errorPos, Res.IncompatibleOperand, opName, GetTypeName(args(0).Type))  
            End If  
            expr = args(0)  
        End Sub  
 
        Private Sub CheckAndPromoteOperands(ByVal signatures As Type, ByVal opName As String, ByRef left As Expression, ByRef right As Expression, ByVal errorPos As Integer)  
            Dim args As Expression() = New Expression() {left, right}  
            Dim method As MethodBase  
            If FindMethod(signatures, "F", False, args, method) <> 1 Then  
                Throw IncompatibleOperandsError(opName, left, right, errorPos)  
            End If  
            left = args(0)  
            right = args(1)  
        End Sub  
 
        Private Function IncompatibleOperandsError(ByVal opName As String, ByVal left As Expression, ByVal right As Expression, ByVal pos As Integer) As Exception  
            Return ParseError(pos, Res.IncompatibleOperands, opName, GetTypeName(left.Type), GetTypeName(right.Type))  
        End Function  
 
        Private Function FindPropertyOrField(ByVal type__1 As Type, ByVal memberName As String, ByVal staticAccess As Boolean) As MemberInfo  
            Dim flags As BindingFlagsBindingFlags = BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or (If(staticAccess, BindingFlags.[Static], BindingFlags.Instance))  
            For Each t As Type In SelfAndBaseTypes(type__1)  
                Dim members As MemberInfo() = t.FindMembers(MemberTypes.[Property] Or MemberTypes.Field, flags, Type.FilterNameIgnoreCase, memberName)  
                If members.Length <> 0 Then  
                    Return members(0)  
                End If  
            Next  
            Return Nothing  
        End Function  
 
        Private Function FindMethod(ByVal type__1 As Type, ByVal methodName As String, ByVal staticAccess As Boolean, ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            Dim flags As BindingFlagsBindingFlags = BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or (If(staticAccess, BindingFlags.[Static], BindingFlags.Instance))  
            For Each t As Type In SelfAndBaseTypes(type__1)  
                Dim members As MemberInfo() = t.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName)  
                Dim count As Integer = FindBestMethod(members.Cast(Of MethodBase)(), args, method)  
                If count <> 0 Then  
                    Return count  
                End If  
            Next  
            method = Nothing 
            Return 0  
        End Function  
 
        Private Function FindIndexer(ByVal type As Type, ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            For Each t As Type In SelfAndBaseTypes(type)  
                Dim members As MemberInfo() = t.GetDefaultMembers()  
                If members.Length <> 0 Then  
                    Dim methods As IEnumerable(Of MethodBase) = members.OfType(Of PropertyInfo)().[Select](Function(p) DirectCast(p.GetGetMethod(), MethodBase)).Where(Function(m) m IsNot Nothing)  
                    Dim count As Integer = FindBestMethod(methods, args, method)  
                    If count <> 0 Then  
                        Return count  
                    End If  
                End If  
            Next  
            method = Nothing 
            Return 0  
        End Function  
 
        Private Shared Function SelfAndBaseTypes(ByVal type As Type) As IEnumerable(Of Type)  
            If type.IsInterface Then  
                Dim types As New List(Of Type)()  
                AddInterface(types, type)  
                Return types  
            End If  
            Return SelfAndBaseClasses(type)  
        End Function  
 
        Private Shared Function SelfAndBaseClasses(ByVal type As Type) As IEnumerable(Of Type)  
            While type IsNot Nothing  
                Return New Type() {type}  
                typetype = type.BaseType  
            End While  
        End Function  
 
        Private Shared Sub AddInterface(ByVal types As List(Of Type), ByVal type As Type)  
            If Not types.Contains(type) Then  
                types.Add(type)  
                For Each t As Type In type.GetInterfaces()  
                    AddInterface(types, t)  
                Next  
            End If  
        End Sub  
 
        Private Class MethodData  
            Public MethodBase As MethodBase  
            Public Parameters As ParameterInfo()  
            Public Args As Expression()  
        End Class  
 
        Private Function FindBestMethod(ByVal methods As IEnumerable(Of MethodBase), ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            Dim applicable As MethodData() = methods.[Select](Function(m) New MethodData() With { _  
              .MethodBase = m, _  
              .Parameters = m.GetParameters() _  
            }).Where(Function(m) IsApplicable(m, args)).ToArray()  
            If applicable.Length > 1 Then  
                applicableapplicable = applicable.Where(Function(m) applicable.All(Function(n) m.Equals(n) OrElse IsBetterThan(args, m, n))).ToArray()  
            End If  
            If applicable.Length = 1 Then  
                Dim md As MethodData = applicable(0)  
                For i As Integer = 0 To args.Length - 1  
                    args(i) = md.Args(i)  
                Next  
                method = md.MethodBase  
            Else  
                method = Nothing 
            End If  
            Return applicable.Length  
        End Function  
 
        Private Function IsApplicable(ByVal method As MethodData, ByVal args As Expression()) As Boolean  
            If method.Parameters.Length <> args.Length Then  
                Return False  
            End If  
            Dim promotedArgs As Expression() = New Expression(args.Length - 1) {}  
            For i As Integer = 0 To args.Length - 1  
                Dim pi As ParameterInfo = method.Parameters(i)  
                If pi.IsOut Then  
                    Return False  
                End If  
                Dim promoted As Expression = PromoteExpression(args(i), pi.ParameterType, False)  
                If promoted Is Nothing Then  
                    Return False  
                End If  
                promotedArgs(i) = promoted  
            Next  
            method.Args = promotedArgs 
            Return True  
        End Function  
 
        Private Function PromoteExpression(ByVal expr As Expression, ByVal type__1 As Type, ByVal exact As Boolean) As Expression  
            If expr.Type.Equals(type__1) Then  
                Return expr  
            End If  
            If TypeOf expr Is ConstantExpression Then  
                Dim ce As ConstantExpression = DirectCast(expr, ConstantExpression)  
                If ce.Equals(nullLiteral) Then  
                    If Not type__1.IsValueType OrElse IsNullableType(type__1) Then  
                        Return Expression.Constant(Nothing, type__1)  
                    End If  
                Else  
                    Dim text As String  
                    If literals.TryGetValue(ce, text) Then  
                        Dim target As Type = GetNonNullableType(type__1)  
                        Dim value As [Object] = Nothing  
                        Select Case Type.GetTypeCode(ce.Type)  
                            Case TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64  
                                value = ParseNumber(text, target)  
                                Exit Select  
                            Case TypeCode.[Double]  
                                If target Is GetType(Decimal) Then  
                                    value = ParseNumber(text, target)  
                                End If  
                                Exit Select  
                            Case TypeCode.[String]  
                                value = ParseEnum(text, target)  
                                Exit Select  
                        End Select  
                        If value IsNot Nothing Then  
                            Return Expression.Constant(value, type__1)  
                        End If  
                    End If  
                End If  
            End If  
            If IsCompatibleWith(expr.Type, type__1) Then  
                If type__1.IsValueType OrElse exact Then  
                    Return Expression.Convert(expr, type__1)  
                End If  
                Return expr  
            End If  
            Return Nothing  
        End Function  
 
        Private Shared Function ParseNumber(ByVal text As String, ByVal type__1 As Type) As Object  
            Select Case Type.GetTypeCode(GetNonNullableType(type__1))  
                Case TypeCode.[SByte]  
                    Dim sb As SByte  
                    If SByte.TryParse(text, sb) Then  
                        Return sb  
                    End If  
                    Exit Select  
                Case TypeCode.[Byte]  
                    Dim b As Byte  
                    If Byte.TryParse(text, b) Then  
                        Return b  
                    End If  
                    Exit Select  
                Case TypeCode.Int16  
                    Dim s As Short  
                    If Short.TryParse(text, s) Then  
                        Return s  
                    End If  
                    Exit Select  
                Case TypeCode.UInt16  
                    Dim us As UShort  
                    If UShort.TryParse(text, us) Then  
                        Return us  
                    End If  
                    Exit Select  
                Case TypeCode.Int32  
                    Dim i As Integer  
                    If Integer.TryParse(text, i) Then  
                        Return i  
                    End If  
                    Exit Select  
                Case TypeCode.UInt32  
                    Dim ui As UInteger  
                    If UInteger.TryParse(text, ui) Then  
                        Return ui  
                    End If  
                    Exit Select  
                Case TypeCode.Int64  
                    Dim l As Long  
                    If Long.TryParse(text, l) Then  
                        Return l  
                    End If  
                    Exit Select  
                Case TypeCode.UInt64  
                    Dim ul As ULong  
                    If ULong.TryParse(text, ul) Then  
                        Return ul  
                    End If  
                    Exit Select  
                Case TypeCode.[Single]  
                    Dim f As Single  
                    If Single.TryParse(text, f) Then  
                        Return f  
                    End If  
                    Exit Select  
                Case TypeCode.[Double]  
                    Dim d As Double  
                    If Double.TryParse(text, d) Then  
                        Return d  
                    End If  
                    Exit Select  
                Case TypeCode.[Decimal]  
                    Dim e As Decimal  
                    If Decimal.TryParse(text, e) Then  
                        Return e  
                    End If  
                    Exit Select  
            End Select  
            Return Nothing  
        End Function  
 
        Private Shared Function ParseEnum(ByVal name As String, ByVal type__1 As Type) As Object  
            If type__1.IsEnum Then  
                Dim memberInfos As MemberInfo() = type__1.FindMembers(MemberTypes.Field, BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or BindingFlags.[Static], Type.FilterNameIgnoreCase, name)  
                If memberInfos.Length <> 0 Then  
                    Return DirectCast(memberInfos(0), FieldInfo).GetValue(Nothing)  
                End If  
            End If  
            Return Nothing  
        End Function  
 
        Private Shared Function IsCompatibleWith(ByVal source As Type, ByVal target As Type) As Boolean  
            If source Is target Then  
                Return True  
            End If  
            If Not target.IsValueType Then  
                Return target.IsAssignableFrom(source)  
            End If  
            Dim st As Type = GetNonNullableType(source)  
            Dim tt As Type = GetNonNullableType(target)  
            If st IsNot source AndAlso tt Is target Then  
                Return False  
            End If  
            Dim sc As TypeCode = If(st.IsEnum, TypeCode.[Object], Type.GetTypeCode(st))  
            Dim tc As TypeCode = If(tt.IsEnum, TypeCode.[Object], Type.GetTypeCode(tt))  
            Select Case sc  
                Case TypeCode.[SByte]  
                    Select Case tc  
                        Case TypeCode.[SByte], TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], _  
                         TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.[Byte]  
                    Select Case tc  
                        Case TypeCode.[Byte], TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, _  
                         TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int16  
                    Select Case tc  
                        Case TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt16  
                    Select Case tc  
                        Case TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.[Single], _  
                         TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int32  
                    Select Case tc  
                        Case TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt32  
                    Select Case tc  
                        Case TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int64  
                    Select Case tc  
                        Case TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt64  
                    Select Case tc  
                        Case TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.[Single]  
                    Select Case tc  
                        Case TypeCode.[Single], TypeCode.[Double]  
                            Return True  
                    End Select  
                    Exit Select  
                Case Else  
                    If st Is tt Then  
                        Return True  
                    End If  
                    Exit Select  
            End Select  
            Return False  
        End Function  
 
        Private Shared Function IsBetterThan(ByVal args As Expression(), ByVal m1 As MethodData, ByVal m2 As MethodData) As Boolean  
            Dim better As Boolean = False 
            For i As Integer = 0 To args.Length - 1  
                Dim c As Integer = CompareConversions(args(i).Type, m1.Parameters(i).ParameterType, m2.Parameters(i).ParameterType)  
                If c < 0 Then  
                    Return False  
                End If  
                If c > 0 Then  
                    better = True 
                End If  
            Next  
            Return better  
        End Function  
 
        ' Return 1 if s -> t1 is a better conversion than s -> t2  
        ' Return -1 if s -> t2 is a better conversion than s -> t1  
        ' Return 0 if neither conversion is better  
        Private Shared Function CompareConversions(ByVal s As Type, ByVal t1 As Type, ByVal t2 As Type) As Integer  
            If t1 Is t2 Then  
                Return 0  
            End If  
            If s Is t1 Then  
                Return 1  
            End If  
            If s Is t2 Then  
                Return -1  
            End If  
            Dim t1t2 As Boolean = IsCompatibleWith(t1, t2)  
            Dim t2t1 As Boolean = IsCompatibleWith(t2, t1)  
            If t1t2 AndAlso Not t2t1 Then  
                Return 1  
            End If  
            If t2t1 AndAlso Not t1t2 Then  
                Return -1  
            End If  
            If IsSignedIntegralType(t1) AndAlso IsUnsignedIntegralType(t2) Then  
                Return 1  
            End If  
            If IsSignedIntegralType(t2) AndAlso IsUnsignedIntegralType(t1) Then  
                Return -1  
            End If  
            Return 0  
        End Function  
 
        Private Function GenerateEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.Equal(left, right)  
        End Function  
 
        Private Function GenerateNotEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.NotEqual(left, right)  
        End Function  
 
        Private Function GenerateGreaterThan(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.GreaterThan(left, right)  
        End Function  
 
        Private Function GenerateGreaterThanEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.GreaterThanOrEqual(left, right)  
        End Function  
 
        Private Function GenerateLessThan(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.LessThan(left, right)  
        End Function  
 
        Private Function GenerateLessThanEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.LessThanOrEqual(left, right)  
        End Function  
 
        Private Function GenerateAdd(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) AndAlso right.Type.Equals(GetType(String)) Then  
                Return GenerateStaticMethodCall("Concat", left, right)  
            End If  
            Return Expression.Add(left, right)  
        End Function  
 
        Private Function GenerateSubtract(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.Subtract(left, right)  
        End Function  
 
        Private Function GenerateStringConcat(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.[Call](Nothing, GetType(String).GetMethod("Concat", New Object() {GetType(Object), GetType(Object)}), New Object() {left, right})  
        End Function  
 
        Private Function GetStaticMethod(ByVal methodName As String, ByVal left As Expression, ByVal right As Expression) As MethodInfo  
            Return left.Type.GetMethod(methodName, New Object() {left.Type, right.Type})  
        End Function  
 
        Private Function GenerateStaticMethodCall(ByVal methodName As String, ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.[Call](Nothing, GetStaticMethod(methodName, left, right), New Object() {left, right})  
        End Function  
 
        Private Sub SetTextPos(ByVal pos As Integer)  
            textPos = pos 
            ch = If(textPos < textLen, text(textPos), ControlChars.NullChar)  
        End Sub  
 
        Private Sub NextChar()  
            If textPos < textLen Then  
                textPos += 1  
            End If  
            ch = If(textPos < textLen, text(textPos), ControlChars.NullChar)  
        End Sub  
 
        Private Sub NextToken()  
            While [Char].IsWhiteSpace(ch)  
                NextChar()  
            End While  
            Dim t As TokenId  
            Dim tokenPos As Integer = textPos 
            Select Case ch  
                Case "!"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.ExclamationEqual  
                    Else  
                        t = TokenId.Exclamation  
                    End If  
                    Exit Select  
                Case "%"c  
                    NextChar()  
                    t = TokenId.Percent  
                    Exit Select  
                Case "&"c  
                    NextChar()  
                    If cch = "&"c Then  
                        NextChar()  
                        t = TokenId.DoubleAmphersand  
                    Else  
                        t = TokenId.Amphersand  
                    End If  
                    Exit Select  
                Case "("c  
                    NextChar()  
                    t = TokenId.OpenParen  
                    Exit Select  
                Case ")"c  
                    NextChar()  
                    t = TokenId.CloseParen  
                    Exit Select  
                Case "*"c  
                    NextChar()  
                    t = TokenId.Asterisk  
                    Exit Select  
                Case "+"c  
                    NextChar()  
                    t = TokenId.Plus  
                    Exit Select  
                Case ","c  
                    NextChar()  
                    t = TokenId.Comma  
                    Exit Select  
                Case "-"c  
                    NextChar()  
                    t = TokenId.Minus  
                    Exit Select  
                Case "."c  
                    NextChar()  
                    t = TokenId.Dot  
                    Exit Select  
                Case "/"c  
                    NextChar()  
                    t = TokenId.Slash  
                    Exit Select  
                Case ":"c  
                    NextChar()  
                    t = TokenId.Colon  
                    Exit Select  
                Case "<"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.LessThanEqual  
                    ElseIf cch = ">"c Then  
                        NextChar()  
                        t = TokenId.LessGreater  
                    Else  
                        t = TokenId.LessThan  
                    End If  
                    Exit Select  
                Case "="c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.DoubleEqual  
                    Else  
                        t = TokenId.Equal  
                    End If  
                    Exit Select  
                Case ">"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.GreaterThanEqual  
                    Else  
                        t = TokenId.GreaterThan  
                    End If  
                    Exit Select  
                Case "?"c  
                    NextChar()  
                    t = TokenId.Question  
                    Exit Select  
                Case "["c  
                    NextChar()  
                    t = TokenId.OpenBracket  
                    Exit Select  
                Case "]"c  
                    NextChar()  
                    t = TokenId.CloseBracket  
                    Exit Select  
                Case "|"c  
                    NextChar()  
                    If cch = "|"c Then  
                        NextChar()  
                        t = TokenId.DoubleBar  
                    Else  
                        t = TokenId.Bar  
                    End If  
                    Exit Select  
                Case """"c, "'"c  
                    Dim quote As Char = ch 
                    Do  
                        NextChar()  
                        While textPos < textLen AndAlso ch <> quote  
                            NextChar()  
                        End While  
                        If textPos = textLen Then  
                            Throw ParseError(textPos, Res.UnterminatedStringLiteral)  
                        End If  
                        NextChar()  
                    Loop While ch = quote 
                    t = TokenId.StringLiteral  
                    Exit Select  
                Case Else  
                    If [Char].IsLetter(ch) OrElse cch = "@"c OrElse cch = "_"c Then  
                        Do  
                            NextChar()  
                        Loop While [Char].IsLetterOrDigit(ch) OrElse cch = "_"c  
                        t = TokenId.Identifier  
                        Exit Select  
                    End If  
                    If [Char].IsDigit(ch) Then  
                        t = TokenId.IntegerLiteral  
                        Do  
                            NextChar()  
                        Loop While [Char].IsDigit(ch)  
                        If cch = "."c Then  
                            t = TokenId.RealLiteral  
                            NextChar()  
                            ValidateDigit()  
                            Do  
                                NextChar()  
                            Loop While [Char].IsDigit(ch)  
                        End If  
                        If cch = "E"c OrElse cch = "e"c Then  
                            t = TokenId.RealLiteral  
                            NextChar()  
                            If cch = "+"c OrElse cch = "-"c Then  
                                NextChar()  
                            End If  
                            ValidateDigit()  
                            Do  
                                NextChar()  
                            Loop While [Char].IsDigit(ch)  
                        End If  
                        If cch = "F"c OrElse cch = "f"c Then  
                            NextChar()  
                        End If  
                        Exit Select  
                    End If  
                    If textPos = textLen Then  
                        t = TokenId.[End]  
                        Exit Select  
                    End If  
                    Throw ParseError(textPos, Res.InvalidCharacter, ch)  
            End Select  
            varToken.id = t 
            varToken.text = text.Substring(tokenPos, textPos - tokenPos)  
            varToken.pos = tokenPos 
        End Sub  
 
        Private Function TokenIdentifierIs(ByVal id As String) As Boolean  
            Return varToken.id = TokenId.Identifier AndAlso [String].Equals(id, varToken.text, StringComparison.OrdinalIgnoreCase)  
        End Function  
 
        Private Function GetIdentifier() As String  
            ValidateToken(TokenId.Identifier, Res.IdentifierExpected)  
            Dim id As String = varToken.text  
            If id.Length > 1 AndAlso id(0) = "@"c Then  
                idid = id.Substring(1)  
            End If  
            Return id  
        End Function  
 
        Private Sub ValidateDigit()  
            If Not [Char].IsDigit(ch) Then  
                Throw ParseError(textPos, Res.DigitExpected)  
            End If  
        End Sub  
 
        Private Sub ValidateToken(ByVal t As TokenId, ByVal errorMessage As String)  
            If varToken.id <> t Then  
                Throw ParseError(errorMessage)  
            End If  
        End Sub  
 
        Private Sub ValidateToken(ByVal t As TokenId)  
            If varToken.id <> t Then  
                Throw ParseError(Res.SyntaxError)  
            End If  
        End Sub  
 
        Private Function ParseError(ByVal format As String, ByVal ParamArray args As Object()) As Exception  
            Return ParseError(varToken.pos, format, args)  
        End Function  
 
        Private Function ParseError(ByVal pos As Integer, ByVal format As String, ByVal ParamArray args As Object()) As Exception  
            Return New ParseException(String.Format(Globalization.CultureInfo.CurrentCulture, format, args), pos)  
        End Function  
 
        Private Shared Function CreateKeywords() As Dictionary(Of String, Object)  
            Dim d As New Dictionary(Of String, Object)(StringComparer.OrdinalIgnoreCase)  
            d.Add("true", trueLiteral)  
            d.Add("false", falseLiteral)  
            d.Add("null", nullLiteral)  
            d.Add(keywordIt, keywordIt)  
            d.Add(keywordIif, keywordIif)  
            d.Add(keywordNew, keywordNew)  
            For Each type As Type In predefinedTypes  
                d.Add(type.Name, type)  
            Next  
            Return d  
        End Function  
        Private Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T  
            target = value 
            Return value  
        End Function  
    End Class  
 
    NotInheritable Class Res  
        Private Sub New()  
        End Sub  
        Public Const DuplicateIdentifier As String = "The identifier '{0}' was defined more than once" 
        Public Const ExpressionTypeMismatch As String = "Expression of type '{0}' expected" 
        Public Const ExpressionExpected As String = "Expression expected" 
        Public Const InvalidCharacterLiteral As String = "Character literal must contain exactly one character" 
        Public Const InvalidIntegerLiteral As String = "Invalid integer literal '{0}'" 
        Public Const InvalidRealLiteral As String = "Invalid real literal '{0}'" 
        Public Const UnknownIdentifier As String = "Unknown identifier '{0}'" 
        Public Const NoItInScope As String = "No 'it' is in scope" 
        Public Const IifRequiresThreeArgs As String = "The 'iif' function requires three arguments" 
        Public Const FirstExprMustBeBool As String = "The first expression must be of type 'Boolean'" 
        Public Const BothTypesConvertToOther As String = "Both of the types '{0}' and '{1}' convert to the other" 
        Public Const NeitherTypeConvertsToOther As String = "Neither of the types '{0}' and '{1}' converts to the other" 
        Public Const MissingAsClause As String = "Expression is missing an 'as' clause" 
        Public Const ArgsIncompatibleWithLambda As String = "Argument list incompatible with lambda expression" 
        Public Const TypeHasNoNullableForm As String = "Type '{0}' has no nullable form" 
        Public Const NoMatchingConstructor As String = "No matching constructor in type '{0}'" 
        Public Const AmbiguousConstructorInvocation As String = "Ambiguous invocation of '{0}' constructor" 
        Public Const CannotConvertValue As String = "A value of type '{0}' cannot be converted to type '{1}'" 
        Public Const NoApplicableMethod As String = "No applicable method '{0}' exists in type '{1}'" 
        Public Const MethodsAreInaccessible As String = "Methods on type '{0}' are not accessible" 
        Public Const MethodIsVoid As String = "Method '{0}' in type '{1}' does not return a value" 
        Public Const AmbiguousMethodInvocation As String = "Ambiguous invocation of method '{0}' in type '{1}'" 
        Public Const UnknownPropertyOrField As String = "No property or field '{0}' exists in type '{1}'" 
        Public Const NoApplicableAggregate As String = "No applicable aggregate method '{0}' exists" 
        Public Const CannotIndexMultiDimArray As String = "Indexing of multi-dimensional arrays is not supported" 
        Public Const InvalidIndex As String = "Array index must be an integer expression" 
        Public Const NoApplicableIndexer As String = "No applicable indexer exists in type '{0}'" 
        Public Const AmbiguousIndexerInvocation As String = "Ambiguous invocation of indexer in type '{0}'" 
        Public Const IncompatibleOperand As String = "Operator '{0}' incompatible with operand type '{1}'" 
        Public Const IncompatibleOperands As String = "Operator '{0}' incompatible with operand types '{1}' and '{2}'" 
        Public Const UnterminatedStringLiteral As String = "Unterminated string literal" 
        Public Const InvalidCharacter As String = "Syntax error '{0}'" 
        Public Const DigitExpected As String = "Digit expected" 
        Public Const SyntaxError As String = "Syntax error" 
        Public Const TokenExpected As String = "{0} expected" 
        Public Const ParseExceptionFormat As String = "{0} (at index {1})" 
        Public Const ColonExpected As String = "':' expected" 
        Public Const OpenParenExpected As String = "'(' expected" 
        Public Const CloseParenOrOperatorExpected As String = "')' or operator expected" 
        Public Const CloseParenOrCommaExpected As String = "')' or ',' expected" 
        Public Const DotOrOpenParenExpected As String = "'.' or '(' expected" 
        Public Const OpenBracketExpected As String = "'[' expected" 
        Public Const CloseBracketOrCommaExpected As String = "']' or ',' expected" 
        Public Const IdentifierExpected As String = "Identifier expected" 
    End Class  
End Namespace 
I have finally converted the DataTable.cs and Dynamic.cs classes from Vlad's serialization example.  I will embed them here for anyone that is interested:
DataTable.vb
Imports System  
Imports System.Collections.Generic  
Imports System.Linq  
Imports System.Collections  
Imports System.Dynamic  
Imports slSQLQueryWizard.SQLWiz.Dynamic  
Namespace SQLWiz.Data  
    Public Class DataTable  
        Implements IEnumerable  
        Public Sub New(ByVal source As IEnumerable(Of Dictionary(Of String, Object)))  
            If source IsNot Nothing Then  
                Dim firstItem = source.FirstOrDefault()  
 
                If firstItem IsNot Nothing Then  
                    For Each key In firstItem  
                        Columns.Add(New DataColumn() With { _  
                         .ColumnName = key.Key, _  
                         .DataType = key.Value.[GetType]() _  
                        })  
                    Next  
 
                    For Each item In source  
                        Dim row = New SQLWiz.Data.myDataRow()  
 
                        For Each key In item  
                            row(key.Key) = key.Value  
                        Next  
                        Rows.Add(row)  
                    Next  
                End If  
            End If  
        End Sub  
 
        Private m_columns As List(Of DataColumn) = Nothing  
        Public ReadOnly Property Columns() As List(Of DataColumn)  
            Get  
                If m_columns Is Nothing Then  
                    m_columns = New List(Of DataColumn)()  
                End If  
 
                Return m_columns  
            End Get  
        End Property  
 
        Private m_rows As List(Of SQLWiz.Data.myDataRow) = Nothing  
        Public ReadOnly Property Rows() As List(Of SQLWiz.Data.myDataRow)  
            Get  
                If m_rows Is Nothing Then  
                    m_rows = New List(Of SQLWiz.Data.myDataRow)()  
                End If  
 
                Return m_rows  
            End Get  
        End Property  
 
        Public Function NewRow() As Object  
            If queryable IsNot Nothing Then  
                Return Activator.CreateInstance(queryable.ElementType)  
            End If  
 
            Return Nothing  
        End Function  
 
#Region "IEnumerable Members"  
 
        Private queryable As IQueryable = Nothing 
        Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator  
            If queryable Is Nothing Then  
                Dim type = ClassFactory.Instance.GetDynamicClass(Me.Columns.[Select](Function(c) New DynamicProperty(c.ColumnName, c.DataType)))  
                Dim propertyInfos = type.GetProperties().ToList()  
 
                Dim mylist = DirectCast(Activator.CreateInstance(GetType(List(Of )).MakeGenericType(type)), IList)  
                For Each row In Me.Rows  
                    Dim item = Activator.CreateInstance(type)  
                    propertyInfos.ForEach(Sub(p) p.SetValue(item, row(p.Name), Nothing))  
                    mylist.Add(item)  
                Next  
 
                queryable = mylist.AsQueryable()  
            End If  
 
            Return queryable.GetEnumerator()  
        End Function  
#End Region  
 
        Public Function ToList() As IList  
            Dim enumerator = GetEnumerator()  
            Dim list = DirectCast(Activator.CreateInstance(GetType(List(Of )).MakeGenericType(queryable.ElementType)), IList)  
            While enumerator.MoveNext()  
                list.Add(enumerator.Current)  
            End While  
            Return list  
        End Function  
    End Class  
 
    Public Class DataColumn  
        Public Sub New()  
            DataType = GetType(Object)  
        End Sub  
 
        Public Property DataType() As Type  
            Get  
                Return m_DataType  
            End Get  
            Set(ByVal value As Type)  
                m_DataType = value 
            End Set  
        End Property  
        Private m_DataType As Type  
        Public Property ColumnName() As String  
            Get  
                Return m_ColumnName  
            End Get  
            Set(ByVal value As String)  
                m_ColumnName = value 
            End Set  
        End Property  
        Private m_ColumnName As String  
    End Class  
 
    Public Class myDataRow  
        Inherits Dictionary(Of String, Object)  
 
        '  
 
    End Class  
End Namespace  
'=======================================================  
'Service provided by Telerik (www.telerik.com)  
'Conversion powered by NRefactory.  
'Twitter: @telerik, @toddanglin  
'Facebook: facebook.com/telerik  
'=======================================================  
 

Dynamic.VB
''Copyright (C) Microsoft Corporation.  All rights reserved.  
 
Imports System.Collections.Generic  
Imports System.Text  
Imports System.Linq  
Imports System.Linq.Expressions  
Imports System.Reflection  
Imports System.Reflection.Emit  
Imports System.Threading  
Imports System.Dynamic  
Imports System.Runtime.CompilerServices  
 
Namespace SQLWiz.Dynamic  
    Module DynamicQueryable  
        Sub New()  
        End Sub  
        <Extension()> _  
        Public Function Where(Of T)(ByVal source As IQueryable(Of T), ByVal predicate As String, ByVal ParamArray values As Object()) As IQueryable(Of T)  
            Return DirectCast(Where(DirectCast(source, IQueryable), predicate, values), IQueryable(Of T))  
        End Function  
 
        <Extension()> _  
        Public Function Where(ByVal source As IQueryable, ByVal predicate As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If predicate Is Nothing Then  
                Throw New ArgumentNullException("predicate")  
            End If  
            Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, GetType(Boolean), predicate, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Where", New Type() {source.ElementType}, source.Expression, Expression.Quote(lambda)))  
        End Function  
 
        <Extension()> _  
        Public Function [Select](ByVal source As IQueryable, ByVal selector As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If selector Is Nothing Then  
                Throw New ArgumentNullException("selector")  
            End If  
            Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, selector, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Select", New Type() {source.ElementType, lambda.Body.Type}, source.Expression, Expression.Quote(lambda)))  
        End Function  
 
        <Extension()> _  
        Public Function OrderBy(Of T)(ByVal source As IQueryable(Of T), ByVal ordering As String, ByVal ParamArray values As Object()) As IQueryable(Of T)  
            Return DirectCast(OrderBy(DirectCast(source, IQueryable), ordering, values), IQueryable(Of T))  
        End Function  
 
        <Extension()> _  
        Public Function OrderBy(ByVal source As IQueryable, ByVal ordering As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If ordering Is Nothing Then  
                Throw New ArgumentNullException("ordering")  
            End If  
            Dim parameters As ParameterExpression() = New ParameterExpression() {Expression.Parameter(source.ElementType, "")}  
            Dim parser As New ExpressionParser(parameters, ordering, values)  
            Dim orderings As IEnumerable(Of DynamicOrdering) = parser.ParseOrdering()  
            Dim queryExpr As Expression = source.Expression  
            Dim methodAsc As String = "OrderBy" 
            Dim methodDesc As String = "OrderByDescending" 
            For Each o As DynamicOrdering In orderings  
                queryExpr = Expression.[Call](GetType(Queryable), If(o.Ascending, methodAsc, methodDesc), New Type() {source.ElementType, o.Selector.Type}, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)))  
                methodAsc = "ThenBy" 
                methodDesc = "ThenByDescending" 
            Next  
            Return source.Provider.CreateQuery(queryExpr)  
        End Function  
 
        <Extension()> _  
        Public Function Take(ByVal source As IQueryable, ByVal count As Integer) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Take", New Type() {source.ElementType}, source.Expression, Expression.Constant(count)))  
        End Function  
 
        <Extension()> _  
        Public Function Skip(ByVal source As IQueryable, ByVal count As Integer) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "Skip", New Type() {source.ElementType}, source.Expression, Expression.Constant(count)))  
        End Function  
 
        <Extension()> _  
        Public Function GroupBy(ByVal source As IQueryable, ByVal keySelector As String, ByVal elementSelector As String, ByVal ParamArray values As Object()) As IQueryable  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            If keySelector Is Nothing Then  
                Throw New ArgumentNullException("keySelector")  
            End If  
            If elementSelector Is Nothing Then  
                Throw New ArgumentNullException("elementSelector")  
            End If  
            Dim keyLambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, keySelector, values)  
            Dim elementLambda As LambdaExpression = DynamicExpression.ParseLambda(source.ElementType, Nothing, elementSelector, values)  
            Return source.Provider.CreateQuery(Expression.[Call](GetType(Queryable), "GroupBy", New Type() {source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type}, source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)))  
        End Function  
 
        <Extension()> _  
        Public Function Any(ByVal source As IQueryable) As Boolean  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return CBool(source.Provider.Execute(Expression.[Call](GetType(Queryable), "Any", New Type() {source.ElementType}, source.Expression)))  
        End Function  
 
        <Extension()> _  
        Public Function Count(ByVal source As IQueryable) As Integer  
            If source Is Nothing Then  
                Throw New ArgumentNullException("source")  
            End If  
            Return CInt(source.Provider.Execute(Expression.[Call](GetType(Queryable), "Count", New Type() {source.ElementType}, source.Expression)))  
        End Function  
    End Module  
 
    Public MustInherit Class DynamicClass  
        Public Overrides Function ToString() As String  
            Dim props As PropertyInfo() = Me.[GetType]().GetProperties(BindingFlags.Instance Or BindingFlags.[Public])  
            Dim sb As New StringBuilder()  
            sb.Append("{")  
            For i As Integer = 0 To props.Length - 1  
                If i > 0 Then  
                    sb.Append(", ")  
                End If  
                sb.Append(props(i).Name)  
                sb.Append("=")  
                sb.Append(props(i).GetValue(Me, Nothing))  
            Next  
            sb.Append("}")  
            Return sb.ToString()  
        End Function  
    End Class  
 
    Public Class DynamicProperty  
        Private m_name As String  
        Private m_type As Type  
 
        Public Sub New(ByVal name As String, ByVal type As Type)  
            If name Is Nothing Then  
                Throw New ArgumentNullException("name")  
            End If  
            If type Is Nothing Then  
                Throw New ArgumentNullException("type")  
            End If  
            Me.m_name = name  
            Me.m_type = type  
        End Sub  
 
        Public ReadOnly Property Name() As String  
            Get  
                Return m_name  
            End Get  
        End Property  
 
        Public ReadOnly Property Type() As Type  
            Get  
                Return m_type  
            End Get  
        End Property  
    End Class  
 
    Module DynamicExpression  
        Sub New()  
        End Sub  
        Public Function Parse(ByVal resultType As Type, ByVal expression As String, ByVal ParamArray values As Object()) As Expression  
            Dim parser As New ExpressionParser(Nothing, expression, values)  
            Return parser.Parse(resultType)  
        End Function  
 
        Public Function ParseLambda(ByVal itType As Type, ByVal resultType As Type, ByVal expression__1 As String, ByVal ParamArray values As Object()) As LambdaExpression  
            Return ParseLambda(New ParameterExpression() {Expression.Parameter(itType, "")}, resultType, expression__1, values)  
        End Function  
 
        Public Function ParseLambda(ByVal parameters As ParameterExpression(), ByVal resultType As Type, ByVal expression__1 As String, ByVal ParamArray values As Object()) As LambdaExpression  
            Dim parser As New ExpressionParser(parameters, expression__1, values)  
            Return Expression.Lambda(parser.Parse(resultType), parameters)  
        End Function  
 
        Public Function ParseLambda(Of T, S)(ByVal expression As String, ByVal ParamArray values As Object()) As Expression(Of Func(Of T, S))  
            Return DirectCast(ParseLambda(GetType(T), GetType(S), expression, values), Expression(Of Func(Of T, S)))  
        End Function  
 
        Public Function CreateClass(ByVal ParamArray properties As DynamicProperty()) As Type  
            Return ClassFactory.Instance.GetDynamicClass(properties)  
        End Function  
 
        Public Function CreateClass(ByVal properties As IEnumerable(Of DynamicProperty)) As Type  
            Return ClassFactory.Instance.GetDynamicClass(properties)  
        End Function  
    End Module  
 
    Friend Class DynamicOrdering  
        Public Selector As Expression  
        Public Ascending As Boolean  
    End Class  
 
    Friend Class Signature  
        Implements IEquatable(Of Signature)  
        Public properties As DynamicProperty()  
        Public hashCode As Integer  
 
        Public Sub New(ByVal properties As IEnumerable(Of DynamicProperty))  
            Me.properties = properties.ToArray()  
            hashCode = 0 
            For Each p As DynamicProperty In properties  
                hashCodehashCode = hashCode Xor p.Name.GetHashCode() Xor p.Type.GetHashCode()  
            Next  
        End Sub  
 
        Public Overrides Function GetHashCode() As Integer  
            Return hashCode  
        End Function  
 
        Public Overrides Function Equals(ByVal obj As Object) As Boolean  
            Return If(TypeOf obj Is Signature, Equals(DirectCast(obj, Signature)), False)  
        End Function  
 
        Public Overloads Function Equals(ByVal other As Signature) As Boolean Implements IEquatable(Of Signature).Equals  
            If properties.Length <> other.properties.Length Then  
                Return False  
            End If  
            For i As Integer = 0 To properties.Length - 1  
                If properties(i).Name <> other.properties(i).Name OrElse properties(i).Type IsNot other.properties(i).Type Then  
                    Return False  
                End If  
            Next  
            Return True  
        End Function  
    End Class  
 
    Friend Class ClassFactory  
        Public Shared ReadOnly Instance As New ClassFactory()  
 
        Shared Sub New()  
        End Sub  
        ' Trigger lazy initialization of static fields  
        Private [module] As ModuleBuilder  
        Private classes As Dictionary(Of Signature, Type)  
        Private classCount As Integer  
 
        Private Sub New()  
            Dim name As New AssemblyName("DynamicClasses")  
            Dim assembly As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run)  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                New ReflectionPermission(PermissionState.Unrestricted).Assert()  
#End If  
            Try  
                [module] = assembly.DefineDynamicModule("Module")  
            Finally  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                PermissionSet.RevertAssert()  
#End If  
            End Try  
            classes = New Dictionary(Of Signature, Type)()  
        End Sub  
 
        Public Function GetDynamicClass(ByVal properties As IEnumerable(Of DynamicProperty)) As Type  
            Try  
                Dim signature As New Signature(properties)  
                Dim type As Type  
                If Not classes.TryGetValue(signature, type) Then  
                    type = CreateDynamicClass(signature.properties)  
                    classes.Add(signature, type)  
                End If  
                Return type  
            Finally  
            End Try  
        End Function  
 
        Private Function CreateDynamicClass(ByVal properties As DynamicProperty()) As Type  
            Try  
                Dim typeName As String = "DynamicClass" & (classCount + 1)  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                    New ReflectionPermission(PermissionState.Unrestricted).Assert()  
#End If  
                Try  
                    Dim tb As TypeBuilder = Me.[module].DefineType(typeName, TypeAttributes.[Class] Or TypeAttributes.[Public], GetType(DynamicClass))  
                    Dim fields As FieldInfo() = GenerateProperties(tb, properties)  
                    GenerateEquals(tb, fields)  
                    GenerateGetHashCode(tb, fields)  
                    Dim result As Type = tb.CreateType()  
                    classCount += 1  
                    Return result  
                Finally  
#If ENABLE_LINQ_PARTIAL_TRUST Then  
                    PermissionSet.RevertAssert()  
#End If  
                End Try  
            Finally  
            End Try  
        End Function  
 
        Private Function GenerateProperties(ByVal tb As TypeBuilder, ByVal properties As DynamicProperty()) As FieldInfo()  
            Dim fields As FieldInfo() = New FieldBuilder(properties.Length - 1) {}  
            For i As Integer = 0 To properties.Length - 1  
                Dim dp As DynamicProperty = properties(i)  
                Dim fb As FieldBuilder = tb.DefineField("_" & dp.Name, dp.Type, FieldAttributes.[Private])  
                Dim pb As PropertyBuilder = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, Nothing)  
                Dim mbGet As MethodBuilder = tb.DefineMethod("get_" & dp.Name, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, dp.Type, Type.EmptyTypes)  
                Dim genGet As ILGenerator = mbGet.GetILGenerator()  
                genGet.Emit(OpCodes.Ldarg_0)  
                genGet.Emit(OpCodes.Ldfld, fb)  
                genGet.Emit(OpCodes.Ret)  
                Dim mbSet As MethodBuilder = tb.DefineMethod("set_" & dp.Name, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, New Type() {dp.Type})  
                Dim genSet As ILGenerator = mbSet.GetILGenerator()  
                genSet.Emit(OpCodes.Ldarg_0)  
                genSet.Emit(OpCodes.Ldarg_1)  
                genSet.Emit(OpCodes.Stfld, fb)  
                genSet.Emit(OpCodes.Ret)  
                pb.SetGetMethod(mbGet)  
                pb.SetSetMethod(mbSet)  
                fields(i) = fb  
            Next  
            Return fields  
        End Function  
 
        Private Sub GenerateEquals(ByVal tb As TypeBuilder, ByVal fields As FieldInfo())  
            Dim mb As MethodBuilder = tb.DefineMethod("Equals", MethodAttributes.[Public] Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig, GetType(Boolean), New Type() {GetType(Object)})  
            Dim gen As ILGenerator = mb.GetILGenerator()  
            Dim other As LocalBuilder = gen.DeclareLocal(tb)  
            Dim [next] As Label = gen.DefineLabel()  
            gen.Emit(OpCodes.Ldarg_1)  
            gen.Emit(OpCodes.Isinst, tb)  
            gen.Emit(OpCodes.Stloc, other)  
            gen.Emit(OpCodes.Ldloc, other)  
            gen.Emit(OpCodes.Brtrue_S, [next])  
            gen.Emit(OpCodes.Ldc_I4_0)  
            gen.Emit(OpCodes.Ret)  
            gen.MarkLabel([next])  
            For Each field As FieldInfo In fields  
                Dim ft As Type = field.FieldType  
                Dim ct As Type = GetType(EqualityComparer(Of )).MakeGenericType(ft)  
                [next] = gen.DefineLabel()  
                gen.EmitCall(OpCodes.[Call], ct.GetMethod("get_Default"), Nothing)  
                gen.Emit(OpCodes.Ldarg_0)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.Emit(OpCodes.Ldloc, other)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", New Type() {ft, ft}), Nothing)  
                gen.Emit(OpCodes.Brtrue_S, [next])  
                gen.Emit(OpCodes.Ldc_I4_0)  
                gen.Emit(OpCodes.Ret)  
                gen.MarkLabel([next])  
            Next  
            gen.Emit(OpCodes.Ldc_I4_1)  
            gen.Emit(OpCodes.Ret)  
        End Sub  
 
        Private Sub GenerateGetHashCode(ByVal tb As TypeBuilder, ByVal fields As FieldInfo())  
            Dim mb As MethodBuilder = tb.DefineMethod("GetHashCode", MethodAttributes.[Public] Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig, GetType(Integer), Type.EmptyTypes)  
            Dim gen As ILGenerator = mb.GetILGenerator()  
            gen.Emit(OpCodes.Ldc_I4_0)  
            For Each field As FieldInfo In fields  
                Dim ft As Type = field.FieldType  
                Dim ct As Type = GetType(EqualityComparer(Of )).MakeGenericType(ft)  
                gen.EmitCall(OpCodes.[Call], ct.GetMethod("get_Default"), Nothing)  
                gen.Emit(OpCodes.Ldarg_0)  
                gen.Emit(OpCodes.Ldfld, field)  
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", New Type() {ft}), Nothing)  
                gen.Emit(OpCodes.[Xor])  
            Next  
            gen.Emit(OpCodes.Ret)  
        End Sub  
    End Class  
 
    Public NotInheritable Class ParseException  
        Inherits Exception  
        Private m_position As Integer  
 
        Public Sub New(ByVal message As String, ByVal position As Integer)  
            MyBase.New(message)  
            Me.m_position = position  
        End Sub  
 
        Public ReadOnly Property Position() As Integer  
            Get  
                Return m_position  
            End Get  
        End Property  
 
        Public Overrides Function ToString() As String  
            Return String.Format(Res.ParseExceptionFormat, Message, m_position)  
        End Function  
    End Class  
 
    Friend Class ExpressionParser  
        Private Structure myToken  
            Public id As TokenId  
            Public text As String  
            Public pos As Integer  
        End Structure  
 
        Private Enum TokenId  
            Unknown  
            [End]  
            Identifier  
            StringLiteral  
            IntegerLiteral  
            RealLiteral  
            Exclamation  
            Percent  
            Amphersand  
            OpenParen  
            CloseParen  
            Asterisk  
            Plus  
            Comma  
            Minus  
            Dot  
            Slash  
            Colon  
            LessThan  
            Equal  
            GreaterThan  
            Question  
            OpenBracket  
            CloseBracket  
            Bar  
            ExclamationEqual  
            DoubleAmphersand  
            LessThanEqual  
            LessGreater  
            DoubleEqual  
            GreaterThanEqual  
            DoubleBar  
        End Enum  
 
        Private Interface ILogicalSignatures  
            Sub F(ByVal x As Boolean, ByVal y As Boolean)  
            Sub F(ByVal x As Global.System.Nullable(Of Boolean), ByVal y As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IArithmeticSignatures  
            Sub F(ByVal x As Integer, ByVal y As Integer)  
            Sub F(ByVal x As UInteger, ByVal y As UInteger)  
            Sub F(ByVal x As Long, ByVal y As Long)  
            Sub F(ByVal x As ULong, ByVal y As ULong)  
            Sub F(ByVal x As Single, ByVal y As Single)  
            Sub F(ByVal x As Double, ByVal y As Double)  
            Sub F(ByVal x As Decimal, ByVal y As Decimal)  
            Sub F(ByVal x As Global.System.Nullable(Of Integer), ByVal y As Global.System.Nullable(Of Integer))  
            Sub F(ByVal x As Global.System.Nullable(Of UInteger), ByVal y As Global.System.Nullable(Of UInteger))  
            Sub F(ByVal x As Global.System.Nullable(Of Long), ByVal y As Global.System.Nullable(Of Long))  
            Sub F(ByVal x As Global.System.Nullable(Of ULong), ByVal y As Global.System.Nullable(Of ULong))  
            Sub F(ByVal x As Global.System.Nullable(Of Single), ByVal y As Global.System.Nullable(Of Single))  
            Sub F(ByVal x As Global.System.Nullable(Of Double), ByVal y As Global.System.Nullable(Of Double))  
            Sub F(ByVal x As Global.System.Nullable(Of Decimal), ByVal y As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Private Interface IRelationalSignatures  
            Inherits IArithmeticSignatures  
            Overloads Sub F(ByVal x As String, ByVal y As String)  
            Overloads Sub F(ByVal x As Char, ByVal y As Char)  
            Overloads Sub F(ByVal x As DateTime, ByVal y As DateTime)  
            Overloads Sub F(ByVal x As TimeSpan, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of Char), ByVal y As Global.System.Nullable(Of Char))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of DateTime))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of TimeSpan), ByVal y As Global.System.Nullable(Of TimeSpan))  
        End Interface  
 
        Private Interface IEqualitySignatures  
            Inherits IRelationalSignatures  
            Overloads Sub F(ByVal x As Boolean, ByVal y As Boolean)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of Boolean), ByVal y As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IAddSignatures  
            Inherits IArithmeticSignatures  
            Overloads Sub F(ByVal x As DateTime, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As TimeSpan, ByVal y As TimeSpan)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of TimeSpan))  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of TimeSpan), ByVal y As Global.System.Nullable(Of TimeSpan))  
        End Interface  
 
        Private Interface ISubtractSignatures  
            Inherits IAddSignatures  
            Overloads Sub F(ByVal x As DateTime, ByVal y As DateTime)  
            Overloads Sub F(ByVal x As Global.System.Nullable(Of DateTime), ByVal y As Global.System.Nullable(Of DateTime))  
        End Interface  
 
        Private Interface INegationSignatures  
            Sub F(ByVal x As Integer)  
            Sub F(ByVal x As Long)  
            Sub F(ByVal x As Single)  
            Sub F(ByVal x As Double)  
            Sub F(ByVal x As Decimal)  
            Sub F(ByVal x As Global.System.Nullable(Of Integer))  
            Sub F(ByVal x As Global.System.Nullable(Of Long))  
            Sub F(ByVal x As Global.System.Nullable(Of Single))  
            Sub F(ByVal x As Global.System.Nullable(Of Double))  
            Sub F(ByVal x As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Private Interface INotSignatures  
            Sub F(ByVal x As Boolean)  
            Sub F(ByVal x As Global.System.Nullable(Of Boolean))  
        End Interface  
 
        Private Interface IEnumerableSignatures  
            Sub Where(ByVal predicate As Boolean)  
            Sub Any()  
            Sub Any(ByVal predicate As Boolean)  
            Sub All(ByVal predicate As Boolean)  
            Sub Count()  
            Sub Count(ByVal predicate As Boolean)  
            Sub Min(ByVal selector As Object)  
            Sub Max(ByVal selector As Object)  
            Sub Sum(ByVal selector As Integer)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Integer))  
            Sub Sum(ByVal selector As Long)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Long))  
            Sub Sum(ByVal selector As Single)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Single))  
            Sub Sum(ByVal selector As Double)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Double))  
            Sub Sum(ByVal selector As Decimal)  
            Sub Sum(ByVal selector As Global.System.Nullable(Of Decimal))  
            Sub Average(ByVal selector As Integer)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Integer))  
            Sub Average(ByVal selector As Long)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Long))  
            Sub Average(ByVal selector As Single)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Single))  
            Sub Average(ByVal selector As Double)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Double))  
            Sub Average(ByVal selector As Decimal)  
            Sub Average(ByVal selector As Global.System.Nullable(Of Decimal))  
        End Interface  
 
        Shared ReadOnly predefinedTypes As Type() = {GetType([Object]), GetType([Boolean]), GetType([Char]), GetType([String]), GetType([SByte]), GetType([Byte]), _  
         GetType(Int16), GetType(UInt16), GetType(Int32), GetType(UInt32), GetType(Int64), GetType(UInt64), _  
         GetType([Single]), GetType([Double]), GetType([Decimal]), GetType(DateTime), GetType(TimeSpan), GetType(Guid), _  
         GetType(Math), GetType(Convert)}  
 
        Shared ReadOnly trueLiteral As ExpressionExpression = Expression.Constant(True)  
        Shared ReadOnly falseLiteral As ExpressionExpression = Expression.Constant(False)  
        Shared ReadOnly nullLiteral As ExpressionExpression = Expression.Constant(Nothing)  
 
        Shared ReadOnly keywordIt As String = "it" 
        Shared ReadOnly keywordIif As String = "iif" 
        Shared ReadOnly keywordNew As String = "new" 
 
        Shared keywords As Dictionary(Of String, Object)  
 
        Private symbols As Dictionary(Of String, Object)  
        Private externals As IDictionary(Of String, Object)  
        Private literals As Dictionary(Of Expression, String)  
        Private it As ParameterExpression  
        Private text As String  
        Private textPos As Integer  
        Private textLen As Integer  
        Private ch As Char  
        Private varToken As myToken  
 
        Public Sub New(ByVal parameters As ParameterExpression(), ByVal expression As String, ByVal values As Object())  
            If expression Is Nothing Then  
                Throw New ArgumentNullException("expression")  
            End If  
            If keywords Is Nothing Then  
                keywords = CreateKeywords()  
            End If  
            symbols = New Dictionary(Of String, Object)(StringComparer.OrdinalIgnoreCase)  
            literals = New Dictionary(Of Expression, String)()  
            If parameters IsNot Nothing Then  
                ProcessParameters(parameters)  
            End If  
            If values IsNot Nothing Then  
                ProcessValues(values)  
            End If  
            text = expression 
            texttextLen = text.Length  
            SetTextPos(0)  
            NextToken()  
        End Sub  
 
        Private Sub ProcessParameters(ByVal parameters As ParameterExpression())  
            For Each pe As ParameterExpression In parameters  
                If Not [String].IsNullOrEmpty(pe.Name) Then  
                    AddSymbol(pe.Name, pe)  
                End If  
            Next  
            If parameters.Length = 1 AndAlso [String].IsNullOrEmpty(parameters(0).Name) Then  
                it = parameters(0)  
            End If  
        End Sub  
 
        Private Sub ProcessValues(ByVal values As Object())  
            For i As Integer = 0 To values.Length - 1  
                Dim value As Object = values(i)  
                If i = values.Length - 1 AndAlso TypeOf value Is IDictionary(Of String, Object) Then  
                    externals = DirectCast(value, IDictionary(Of String, Object))  
                Else  
                    AddSymbol("@" & i.ToString(Globalization.CultureInfo.InvariantCulture), value)  
                End If  
            Next  
        End Sub  
 
        Private Sub AddSymbol(ByVal name As String, ByVal value As Object)  
            If symbols.ContainsKey(name) Then  
                Throw ParseError(Res.DuplicateIdentifier, name)  
            End If  
            symbols.Add(name, value)  
        End Sub  
 
        Public Function Parse(ByVal resultType As Type) As Expression  
            Dim exprPos As Integer = varToken.pos  
            Dim expr As Expression = ParseExpression()  
            If resultType IsNot Nothing Then  
                If (InlineAssignHelper(expr, PromoteExpression(expr, resultType, True))) Is Nothing Then  
                    Throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType))  
                End If  
            End If  
            ValidateToken(TokenId.[End], Res.SyntaxError)  
            Return expr  
        End Function  
 
        '#Pragma warning disable 0219  
        Public Function ParseOrdering() As IEnumerable(Of DynamicOrdering)  
            Dim orderings As New List(Of DynamicOrdering)()  
            While True  
                Dim expr As Expression = ParseExpression()  
                Dim ascending As Boolean = True 
                If TokenIdentifierIs("asc") OrElse TokenIdentifierIs("ascending") Then  
                    NextToken()  
                ElseIf TokenIdentifierIs("desc") OrElse TokenIdentifierIs("descending") Then  
                    NextToken()  
                    ascending = False 
                End If  
                orderings.Add(New DynamicOrdering() With { _  
                  .Selector = expr, _  
                  .Ascending = ascending _  
                })  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            ValidateToken(TokenId.[End], Res.SyntaxError)  
            Return orderings  
        End Function  
        '#Pragma warning restore 0219  
 
        ' ?: operator  
        Private Function ParseExpression() As Expression  
            Dim errorPos As Integer = varToken.pos  
            Dim expr As Expression = ParseLogicalOr()  
            If varToken.id = TokenId.Question Then  
                NextToken()  
                Dim expr1 As Expression = ParseExpression()  
                ValidateToken(TokenId.Colon, Res.ColonExpected)  
                NextToken()  
                Dim expr2 As Expression = ParseExpression()  
                expr = GenerateConditional(expr, expr1, expr2, errorPos)  
            End If  
            Return expr  
        End Function  
 
        ' ||, or operator  
        Private Function ParseLogicalOr() As Expression  
            Dim left As Expression = ParseLogicalAnd()  
            While varToken.id = TokenId.DoubleBar OrElse TokenIdentifierIs("or")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseLogicalAnd()  
                CheckAndPromoteOperands(GetType(ILogicalSignatures), op.text, left, right, op.pos)  
                left = Expression.[OrElse](left, right)  
            End While  
            Return left  
        End Function  
 
        ' &&, and operator  
        Private Function ParseLogicalAnd() As Expression  
            Dim left As Expression = ParseComparison()  
            While varToken.id = TokenId.DoubleAmphersand OrElse TokenIdentifierIs("and")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseComparison()  
                CheckAndPromoteOperands(GetType(ILogicalSignatures), op.text, left, right, op.pos)  
                left = Expression.[AndAlso](left, right)  
            End While  
            Return left  
        End Function  
 
        ' =, ==, !=, <>, >>=, <<= operators  
        Private Function ParseComparison() As Expression  
            Dim left As Expression = ParseAdditive()  
            While varToken.id = TokenId.Equal OrElse varToken.id = TokenId.DoubleEqual OrElse varToken.id = TokenId.ExclamationEqual OrElse varToken.id = TokenId.LessGreater OrElse varToken.id = TokenId.GreaterThan OrElse varToken.id = TokenId.GreaterThanEqual OrElse varToken.id = TokenId.LessThan OrElse varToken.id = TokenId.LessThanEqual  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseAdditive()  
                Dim isEquality As Boolean = op.id = TokenId.Equal OrElse op.id = TokenId.DoubleEqual OrElse op.id = TokenId.ExclamationEqual OrElse op.id = TokenId.LessGreater  
                If isEquality AndAlso Not left.Type.IsValueType AndAlso Not right.Type.IsValueType Then  
                    If Not left.Type.Equals(right.Type) Then  
                        If left.Type.IsAssignableFrom(right.Type) Then  
                            right = Expression.Convert(right, left.Type)  
                        ElseIf right.Type.IsAssignableFrom(left.Type) Then  
                            left = Expression.Convert(left, right.Type)  
                        Else  
                            Throw IncompatibleOperandsError(op.text, left, right, op.pos)  
                        End If  
                    End If  
                ElseIf IsEnumType(left.Type) OrElse IsEnumType(right.Type) Then  
                    If Not left.Type.Equals(right.Type) Then  
                        Dim e As Expression  
                        If (InlineAssignHelper(e, PromoteExpression(right, left.Type, True))) IsNot Nothing Then  
                            right = e 
                        ElseIf (InlineAssignHelper(e, PromoteExpression(left, right.Type, True))) IsNot Nothing Then  
                            left = e  
                        Else  
                            Throw IncompatibleOperandsError(op.text, left, right, op.pos)  
                        End If  
                    End If  
                Else  
                    CheckAndPromoteOperands(If(isEquality, GetType(IEqualitySignatures), GetType(IRelationalSignatures)), op.text, left, right, op.pos)  
                End If  
                Select Case op.id  
                    Case TokenId.Equal, TokenId.DoubleEqual  
                        left = GenerateEqual(left, right)  
                        Exit Select  
                    Case TokenId.ExclamationEqual, TokenId.LessGreater  
                        left = GenerateNotEqual(left, right)  
                        Exit Select  
                    Case TokenId.GreaterThan  
                        left = GenerateGreaterThan(left, right)  
                        Exit Select  
                    Case TokenId.GreaterThanEqual  
                        left = GenerateGreaterThanEqual(left, right)  
                        Exit Select  
                    Case TokenId.LessThan  
                        left = GenerateLessThan(left, right)  
                        Exit Select  
                    Case TokenId.LessThanEqual  
                        left = GenerateLessThanEqual(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' +, -, & operators  
        Private Function ParseAdditive() As Expression  
            Dim left As Expression = ParseMultiplicative()  
            While varToken.id = TokenId.Plus OrElse varToken.id = TokenId.Minus OrElse varToken.id = TokenId.Amphersand  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseMultiplicative()  
                Select Case op.id  
                    Case TokenId.Plus  
                        If left.Type.Equals(GetType(String)) OrElse right.Type.Equals(GetType(String)) Then  
                            left = GenerateStringConcat(left, right)  
                            Exit Select  
                        End If  
                        CheckAndPromoteOperands(GetType(IAddSignatures), op.text, left, right, op.pos)  
                        left = GenerateAdd(left, right)  
                        Exit Select  
                    Case TokenId.Minus  
                        CheckAndPromoteOperands(GetType(ISubtractSignatures), op.text, left, right, op.pos)  
                        left = GenerateSubtract(left, right)  
                        Exit Select  
                    Case TokenId.Amphersand  
                        left = GenerateStringConcat(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' *, /, %, mod operators  
        Private Function ParseMultiplicative() As Expression  
            Dim left As Expression = ParseUnary()  
            While varToken.id = TokenId.Asterisk OrElse varToken.id = TokenId.Slash OrElse varToken.id = TokenId.Percent OrElse TokenIdentifierIs("mod")  
                Dim op As myToken = varToken 
                NextToken()  
                Dim right As Expression = ParseUnary()  
                CheckAndPromoteOperands(GetType(IArithmeticSignatures), op.text, left, right, op.pos)  
                Select Case op.id  
                    Case TokenId.Asterisk  
                        left = Expression.Multiply(left, right)  
                        Exit Select  
                    Case TokenId.Slash  
                        left = Expression.Divide(left, right)  
                        Exit Select  
                    Case TokenId.Percent, TokenId.Identifier  
                        left = Expression.Modulo(left, right)  
                        Exit Select  
                End Select  
            End While  
            Return left  
        End Function  
 
        ' -, !, not unary operators  
        Private Function ParseUnary() As Expression  
            If varToken.id = TokenId.Minus OrElse varToken.id = TokenId.Exclamation OrElse TokenIdentifierIs("not") Then  
                Dim op As myToken = varToken 
                NextToken()  
                If op.id = TokenId.Minus AndAlso (varToken.id = TokenId.IntegerLiteral OrElse varToken.id = TokenId.RealLiteral) Then  
                    varToken.text = "-" & varToken.text  
                    varToken.pos = op.pos  
                    Return ParsePrimary()  
                End If  
                Dim expr As Expression = ParseUnary()  
                If op.id = TokenId.Minus Then  
                    CheckAndPromoteOperand(GetType(INegationSignatures), op.text, expr, op.pos)  
                    expr = Expression.Negate(expr)  
                Else  
                    CheckAndPromoteOperand(GetType(INotSignatures), op.text, expr, op.pos)  
                    expr = Expression.[Not](expr)  
                End If  
                Return expr  
            End If  
            Return ParsePrimary()  
        End Function  
 
        Private Function ParsePrimary() As Expression  
            Dim expr As Expression = ParsePrimaryStart()  
            While True  
                If varToken.id = TokenId.Dot Then  
                    NextToken()  
                    expr = ParseMemberAccess(Nothing, expr)  
                ElseIf varToken.id = TokenId.OpenBracket Then  
                    expr = ParseElementAccess(expr)  
                Else  
                    Exit While  
                End If  
            End While  
            Return expr  
        End Function  
 
        Private Function ParsePrimaryStart() As Expression  
            Select Case varToken.id  
                Case TokenId.Identifier  
                    Return ParseIdentifier()  
                Case TokenId.StringLiteral  
                    Return ParseStringLiteral()  
                Case TokenId.IntegerLiteral  
                    Return ParseIntegerLiteral()  
                Case TokenId.RealLiteral  
                    Return ParseRealLiteral()  
                Case TokenId.OpenParen  
                    Return ParseParenExpression()  
                Case Else  
                    Throw ParseError(Res.ExpressionExpected)  
            End Select  
        End Function  
 
        Private Function ParseStringLiteral() As Expression  
            ValidateToken(TokenId.StringLiteral)  
            Dim quote As Char = varToken.text(0)  
            Dim s As String = varToken.text.Substring(1, varToken.text.Length - 2)  
            Dim start As Integer = 0 
            While True  
                Dim i As Integer = s.IndexOf(quote, start)  
                If i < 0 Then  
                    Exit While  
                End If  
                ss = s.Remove(i, 1)  
                start = i + 1  
            End While  
            If quote = "'"c Then  
                If s.Length <> 1 Then  
                    Throw ParseError(Res.InvalidCharacterLiteral)  
                End If  
                NextToken()  
                Return CreateLiteral(s(0), s)  
            End If  
            NextToken()  
            Return CreateLiteral(s, s)  
        End Function  
 
        Private Function ParseIntegerLiteral() As Expression  
            ValidateToken(TokenId.IntegerLiteral)  
            Dim text As String = varToken.text  
            If text(0) <> "-"c Then  
                Dim value As ULong  
                If Not UInt64.TryParse(text, value) Then  
                    Throw ParseError(Res.InvalidIntegerLiteral, text)  
                End If  
                NextToken()  
                If value <= CULng(Int32.MaxValue) Then  
                    Return CreateLiteral(CInt(value), text)  
                End If  
                If value <= CULng(UInt32.MaxValue) Then  
                    Return CreateLiteral(CUInt(value), text)  
                End If  
                If value <= CULng(Int64.MaxValue) Then  
                    Return CreateLiteral(CLng(value), text)  
                End If  
                Return CreateLiteral(value, text)  
            Else  
                Dim value As Long  
                If Not Int64.TryParse(text, value) Then  
                    Throw ParseError(Res.InvalidIntegerLiteral, text)  
                End If  
                NextToken()  
                If value >= Int32.MinValue AndAlso value <= Int32.MaxValue Then  
                    Return CreateLiteral(CInt(value), text)  
                End If  
                Return CreateLiteral(value, text)  
            End If  
        End Function  
 
        Private Function ParseRealLiteral() As Expression  
            ValidateToken(TokenId.RealLiteral)  
            Dim text As String = varToken.text  
            Dim value As Object = Nothing 
            Dim last As Char = text(text.Length - 1)  
            If last = "F"c OrElse last = "f"c Then  
                Dim f As Single  
                If [Single].TryParse(text.Substring(0, text.Length - 1), f) Then  
                    value = f 
                End If  
            Else  
                Dim d As Double  
                If [Double].TryParse(text, d) Then  
                    value = d 
                End If  
            End If  
            If value Is Nothing Then  
                Throw ParseError(Res.InvalidRealLiteral, text)  
            End If  
            NextToken()  
            Return CreateLiteral(value, text)  
        End Function  
 
        Private Function CreateLiteral(ByVal value As Object, ByVal text As String) As Expression  
            Dim expr As ConstantExpression = Expression.Constant(value)  
            literals.Add(expr, text)  
            Return expr  
        End Function  
 
        Private Function ParseParenExpression() As Expression  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim e As Expression = ParseExpression()  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected)  
            NextToken()  
            Return e  
        End Function  
 
        Private Function ParseIdentifier() As Expression  
            ValidateToken(TokenId.Identifier)  
            Dim value As Object  
            If keywords.TryGetValue(varToken.text, value) Then  
                If TypeOf value Is Type Then  
                    Return ParseTypeAccess(DirectCast(value, Type))  
                End If  
                If value Is DirectCast(keywordIt, Object) Then  
                    Return ParseIt()  
                End If  
                If value Is DirectCast(keywordIif, Object) Then  
                    Return ParseIif()  
                End If  
                If value Is DirectCast(keywordNew, Object) Then  
                    Return ParseNew()  
                End If  
                NextToken()  
                Return DirectCast(value, Expression)  
            End If  
            If symbols.TryGetValue(varToken.text, value) OrElse externals IsNot Nothing AndAlso externals.TryGetValue(varToken.text, value) Then  
                Dim expr As Expression = TryCast(value, Expression)  
                If expr Is Nothing Then  
                    expr = Expression.Constant(value)  
                Else  
                    Dim lambda As LambdaExpression = TryCast(expr, LambdaExpression)  
                    If lambda IsNot Nothing Then  
                        Return ParseLambdaInvocation(lambda)  
                    End If  
                End If  
                NextToken()  
                Return expr  
            End If  
            If it IsNot Nothing Then  
                Return ParseMemberAccess(Nothing, it)  
            End If  
            Throw ParseError(Res.UnknownIdentifier, varToken.text)  
        End Function  
 
        Private Function ParseIt() As Expression  
            If it Is Nothing Then  
                Throw ParseError(Res.NoItInScope)  
            End If  
            NextToken()  
            Return it  
        End Function  
 
        Private Function ParseIif() As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            Dim args As Expression() = ParseArgumentList()  
            If args.Length <> 3 Then  
                Throw ParseError(errorPos, Res.IifRequiresThreeArgs)  
            End If  
            Return GenerateConditional(args(0), args(1), args(2), errorPos)  
        End Function  
 
        Private Function GenerateConditional(ByVal test As Expression, ByVal expr1 As Expression, ByVal expr2 As Expression, ByVal errorPos As Integer) As Expression  
            If Not test.Type.Equals(GetType(Boolean)) Then  
                Throw ParseError(errorPos, Res.FirstExprMustBeBool)  
            End If  
            If Not expr1.Type.Equals(expr2.Type) Then  
                Dim expr1as2 As Expression = If(Not expr2.Equals(nullLiteral), PromoteExpression(expr1, expr2.Type, True), Nothing)  
                Dim expr2as1 As Expression = If(Not expr2.Equals(nullLiteral), PromoteExpression(expr2, expr1.Type, True), Nothing)  
                If expr1as2 IsNot Nothing AndAlso expr2as1 Is Nothing Then  
                    expr1 = expr1as2 
                ElseIf expr2as1 IsNot Nothing AndAlso expr1as2 Is Nothing Then  
                    expr2 = expr2as1 
                Else  
                    Dim type1 As String = If(Not expr2.Equals(nullLiteral), expr1.Type.Name, "null")  
                    Dim type2 As String = If(Not expr2.Equals(nullLiteral), expr2.Type.Name, "null")  
                    If expr1as2 IsNot Nothing AndAlso expr2as1 IsNot Nothing Then  
                        Throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2)  
                    End If  
                    Throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2)  
                End If  
            End If  
            Return Expression.Condition(test, expr1, expr2)  
        End Function  
 
        Private Function ParseNew() As Expression  
            NextToken()  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim properties As New List(Of DynamicProperty)()  
            Dim expressions As New List(Of Expression)()  
            While True  
                Dim exprPos As Integer = varToken.pos  
                Dim expr As Expression = ParseExpression()  
                Dim propName As String  
                If TokenIdentifierIs("as") Then  
                    NextToken()  
                    propName = GetIdentifier()  
                    NextToken()  
                Else  
                    Dim [me] As MemberExpression = TryCast(expr, MemberExpression)  
                    If [me] Is Nothing Then  
                        Throw ParseError(exprPos, Res.MissingAsClause)  
                    End If  
                    propName = [me].Member.Name  
                End If  
                expressions.Add(expr)  
                properties.Add(New DynamicProperty(propName, expr.Type))  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected)  
            NextToken()  
            Dim type As Type = DynamicExpression.CreateClass(properties)  
            Dim bindings As MemberBinding() = New MemberBinding(properties.Count - 1) {}  
            For i As Integer = 0 To bindings.Length - 1  
                bindings(i) = Expression.Bind(type.GetProperty(properties(i).Name), expressions(i))  
            Next  
            Return Expression.MemberInit(Expression.[New](type), bindings)  
        End Function  
 
        Private Function ParseLambdaInvocation(ByVal lambda As LambdaExpression) As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            Dim args As Expression() = ParseArgumentList()  
            Dim method As MethodBase  
            If FindMethod(lambda.Type, "Invoke", False, args, method) <> 1 Then  
                Throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda)  
            End If  
            Return Expression.Invoke(lambda, args)  
        End Function  
 
        Private Function ParseTypeAccess(ByVal type As Type) As Expression  
            Dim errorPos As Integer = varToken.pos  
            NextToken()  
            If varToken.id = TokenId.Question Then  
                If Not type.IsValueType OrElse IsNullableType(type) Then  
                    Throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type))  
                End If  
                type = GetType(Nullable(Of )).MakeGenericType(type)  
                NextToken()  
            End If  
            If varToken.id = TokenId.OpenParen Then  
                Dim args As Expression() = ParseArgumentList()  
                Dim method As MethodBase  
                Select Case FindBestMethod(type.GetConstructors(), args, method)  
                    Case 0  
                        If args.Length = 1 Then  
                            Return GenerateConversion(args(0), type, errorPos)  
                        End If  
                        Throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type))  
                    Case 1  
                        Return Expression.[New](DirectCast(method, ConstructorInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type))  
                End Select  
            End If  
            ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected)  
            NextToken()  
            Return ParseMemberAccess(type, Nothing)  
        End Function  
 
        Private Function GenerateConversion(ByVal expr As Expression, ByVal type As Type, ByVal errorPos As Integer) As Expression  
            Dim exprType As Type = expr.Type  
            If exprType Is type Then  
                Return expr  
            End If  
            If exprType.IsValueType AndAlso type.IsValueType Then  
                If (IsNullableType(exprType) OrElse IsNullableType(type)) AndAlso GetNonNullableType(exprType) Is GetNonNullableType(type) Then  
                    Return Expression.Convert(expr, type)  
                End If  
                If (IsNumericType(exprType) OrElse IsEnumType(exprType)) AndAlso (IsNumericType(type)) OrElse IsEnumType(type) Then  
                    Return Expression.ConvertChecked(expr, type)  
                End If  
            End If  
            If exprType.IsAssignableFrom(type) OrElse type.IsAssignableFrom(exprType) OrElse exprType.IsInterface OrElse type.IsInterface Then  
                Return Expression.Convert(expr, type)  
            End If  
            Throw ParseError(errorPos, Res.CannotConvertValue, GetTypeName(exprType), GetTypeName(type))  
        End Function  
 
        Private Function ParseMemberAccess(ByVal type As Type, ByVal instance As Expression) As Expression  
            If instance IsNot Nothing Then  
                type = instance.Type  
            End If  
            Dim errorPos As Integer = varToken.pos  
            Dim id As String = GetIdentifier()  
            NextToken()  
            If varToken.id = TokenId.OpenParen Then  
                If instance IsNot Nothing AndAlso type IsNot GetType(String) Then  
                    Dim enumerableType As Type = FindGenericType(GetType(IEnumerable(Of )), type)  
                    If enumerableType IsNot Nothing Then  
                        Dim elementType As Type = enumerableType.GetGenericArguments()(0)  
                        Return ParseAggregate(instance, elementType, id, errorPos)  
                    End If  
                End If  
                Dim args As Expression() = ParseArgumentList()  
                Dim mb As MethodBase  
                Select Case FindMethod(type, id, instance Is Nothing, args, mb)  
                    Case 0  
                        Throw ParseError(errorPos, Res.NoApplicableMethod, id, GetTypeName(type))  
                    Case 1  
                        Dim method As MethodInfo = DirectCast(mb, MethodInfo)  
                        If Not IsPredefinedType(method.DeclaringType) Then  
                            Throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType))  
                        End If  
                        If method.ReturnType Is GetType(Void) Then  
                            Throw ParseError(errorPos, Res.MethodIsVoid, id, GetTypeName(method.DeclaringType))  
                        End If  
                        Return Expression.[Call](instance, DirectCast(method, MethodInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousMethodInvocation, id, GetTypeName(type))  
                End Select  
            Else  
                Dim member As MemberInfo = FindPropertyOrField(type, id, instance Is Nothing)  
                If member Is Nothing Then  
                    Throw ParseError(errorPos, Res.UnknownPropertyOrField, id, GetTypeName(type))  
                End If  
                Return If(TypeOf member Is PropertyInfo, Expression.[Property](instance, DirectCast(member, PropertyInfo)), Expression.Field(instance, DirectCast(member, FieldInfo)))  
            End If  
        End Function  
 
        Private Shared Function FindGenericType(ByVal generic As Type, ByVal type As Type) As Type  
            While type IsNot Nothing AndAlso type IsNot GetType(Object)  
                If type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is generic Then  
                    Return type  
                End If  
                If generic.IsInterface Then  
                    For Each intfType As Type In type.GetInterfaces()  
                        Dim found As Type = FindGenericType(generic, intfType)  
                        If found IsNot Nothing Then  
                            Return found  
                        End If  
                    Next  
                End If  
                typetype = type.BaseType  
            End While  
            Return Nothing  
        End Function  
 
        Private Function ParseAggregate(ByVal instance As Expression, ByVal elementType As Type, ByVal methodName As String, ByVal errorPos As Integer) As Expression  
            Dim outerIt As ParameterExpression = it 
            Dim innerIt As ParameterExpression = Expression.Parameter(elementType, "")  
            it = innerIt 
            Dim args As Expression() = ParseArgumentList()  
            it = outerIt 
            Dim signature As MethodBase  
            If FindMethod(GetType(IEnumerableSignatures), methodName, False, args, signature) <> 1 Then  
                Throw ParseError(errorPos, Res.NoApplicableAggregate, methodName)  
            End If  
            Dim typeArgs As Type()  
            If signature.Name = "Min" OrElse signature.Name = "Max" Then  
                typeArgs = New Type() {elementType, args(0).Type}  
            Else  
                typeArgs = New Type() {elementType}  
            End If  
            If args.Length = 0 Then  
                args = New Expression() {instance}  
            Else  
                args = New Expression() {instance, Expression.Lambda(args(0), innerIt)}  
            End If  
            Return Expression.[Call](GetType(Enumerable), signature.Name, typeArgs, args)  
        End Function  
 
        Private Function ParseArgumentList() As Expression()  
            ValidateToken(TokenId.OpenParen, Res.OpenParenExpected)  
            NextToken()  
            Dim args As Expression() = If(varToken.id <> TokenId.CloseParen, ParseArguments(), New Expression(-1) {})  
            ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected)  
            NextToken()  
            Return args  
        End Function  
 
        Private Function ParseArguments() As Expression()  
            Dim argList As New List(Of Expression)()  
            While True  
                argList.Add(ParseExpression())  
                If varToken.id <> TokenId.Comma Then  
                    Exit While  
                End If  
                NextToken()  
            End While  
            Return argList.ToArray()  
        End Function  
 
        Private Function ParseElementAccess(ByVal expr As Expression) As Expression  
            Dim errorPos As Integer = varToken.pos  
            ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected)  
            NextToken()  
            Dim args As Expression() = ParseArguments()  
            ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected)  
            NextToken()  
            If expr.Type.IsArray Then  
                If expr.Type.GetArrayRank() <> 1 OrElse args.Length <> 1 Then  
                    Throw ParseError(errorPos, Res.CannotIndexMultiDimArray)  
                End If  
                Dim index As Expression = PromoteExpression(args(0), GetType(Integer), True)  
                If index Is Nothing Then  
                    Throw ParseError(errorPos, Res.InvalidIndex)  
                End If  
                Return Expression.ArrayIndex(expr, index)  
            Else  
                Dim mb As MethodBase  
                Select Case FindIndexer(expr.Type, args, mb)  
                    Case 0  
                        Throw ParseError(errorPos, Res.NoApplicableIndexer, GetTypeName(expr.Type))  
                    Case 1  
                        Return Expression.[Call](expr, DirectCast(mb, MethodInfo), args)  
                    Case Else  
                        Throw ParseError(errorPos, Res.AmbiguousIndexerInvocation, GetTypeName(expr.Type))  
                End Select  
            End If  
        End Function  
 
        Private Shared Function IsPredefinedType(ByVal type As Type) As Boolean  
            For Each t As Type In predefinedTypes  
                If t Is type Then  
                    Return True  
                End If  
            Next  
            Return False  
        End Function  
 
        Private Shared Function IsNullableType(ByVal type As Type) As Boolean  
            Return type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is GetType(Nullable(Of ))  
        End Function  
 
        Private Shared Function GetNonNullableType(ByVal type As Type) As Type  
            Return If(IsNullableType(type), type.GetGenericArguments()(0), type)  
        End Function  
 
        Private Shared Function GetTypeName(ByVal type As Type) As String  
            Dim baseType As Type = GetNonNullableType(type)  
            Dim s As String = baseType.Name  
            If type IsNot baseType Then  
                s += "?"c  
            End If  
            Return s  
        End Function  
 
        Private Shared Function IsNumericType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) <> 0  
        End Function  
 
        Private Shared Function IsSignedIntegralType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) = 2  
        End Function  
 
        Private Shared Function IsUnsignedIntegralType(ByVal type As Type) As Boolean  
            Return GetNumericTypeKind(type) = 3  
        End Function  
 
        Private Shared Function GetNumericTypeKind(ByVal type__1 As Type) As Integer  
            type__1 = GetNonNullableType(type__1)  
            If type__1.IsEnum Then  
                Return 0  
            End If  
            Select Case Type.GetTypeCode(type__1)  
                Case TypeCode.[Char], TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                    Return 1  
                Case TypeCode.[SByte], TypeCode.Int16, TypeCode.Int32, TypeCode.Int64  
                    Return 2  
                Case TypeCode.[Byte], TypeCode.UInt16, TypeCode.UInt32, TypeCode.UInt64  
                    Return 3  
                Case Else  
                    Return 0  
            End Select  
        End Function  
 
        Private Shared Function IsEnumType(ByVal type As Type) As Boolean  
            Return GetNonNullableType(type).IsEnum  
        End Function  
 
        Private Sub CheckAndPromoteOperand(ByVal signatures As Type, ByVal opName As String, ByRef expr As Expression, ByVal errorPos As Integer)  
            Dim args As Expression() = New Expression() {expr}  
            Dim method As MethodBase  
            If FindMethod(signatures, "F", False, args, method) <> 1 Then  
                Throw ParseError(errorPos, Res.IncompatibleOperand, opName, GetTypeName(args(0).Type))  
            End If  
            expr = args(0)  
        End Sub  
 
        Private Sub CheckAndPromoteOperands(ByVal signatures As Type, ByVal opName As String, ByRef left As Expression, ByRef right As Expression, ByVal errorPos As Integer)  
            Dim args As Expression() = New Expression() {left, right}  
            Dim method As MethodBase  
            If FindMethod(signatures, "F", False, args, method) <> 1 Then  
                Throw IncompatibleOperandsError(opName, left, right, errorPos)  
            End If  
            left = args(0)  
            right = args(1)  
        End Sub  
 
        Private Function IncompatibleOperandsError(ByVal opName As String, ByVal left As Expression, ByVal right As Expression, ByVal pos As Integer) As Exception  
            Return ParseError(pos, Res.IncompatibleOperands, opName, GetTypeName(left.Type), GetTypeName(right.Type))  
        End Function  
 
        Private Function FindPropertyOrField(ByVal type__1 As Type, ByVal memberName As String, ByVal staticAccess As Boolean) As MemberInfo  
            Dim flags As BindingFlagsBindingFlags = BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or (If(staticAccess, BindingFlags.[Static], BindingFlags.Instance))  
            For Each t As Type In SelfAndBaseTypes(type__1)  
                Dim members As MemberInfo() = t.FindMembers(MemberTypes.[Property] Or MemberTypes.Field, flags, Type.FilterNameIgnoreCase, memberName)  
                If members.Length <> 0 Then  
                    Return members(0)  
                End If  
            Next  
            Return Nothing  
        End Function  
 
        Private Function FindMethod(ByVal type__1 As Type, ByVal methodName As String, ByVal staticAccess As Boolean, ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            Dim flags As BindingFlagsBindingFlags = BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or (If(staticAccess, BindingFlags.[Static], BindingFlags.Instance))  
            For Each t As Type In SelfAndBaseTypes(type__1)  
                Dim members As MemberInfo() = t.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName)  
                Dim count As Integer = FindBestMethod(members.Cast(Of MethodBase)(), args, method)  
                If count <> 0 Then  
                    Return count  
                End If  
            Next  
            method = Nothing 
            Return 0  
        End Function  
 
        Private Function FindIndexer(ByVal type As Type, ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            For Each t As Type In SelfAndBaseTypes(type)  
                Dim members As MemberInfo() = t.GetDefaultMembers()  
                If members.Length <> 0 Then  
                    Dim methods As IEnumerable(Of MethodBase) = members.OfType(Of PropertyInfo)().[Select](Function(p) DirectCast(p.GetGetMethod(), MethodBase)).Where(Function(m) m IsNot Nothing)  
                    Dim count As Integer = FindBestMethod(methods, args, method)  
                    If count <> 0 Then  
                        Return count  
                    End If  
                End If  
            Next  
            method = Nothing 
            Return 0  
        End Function  
 
        Private Shared Function SelfAndBaseTypes(ByVal type As Type) As IEnumerable(Of Type)  
            If type.IsInterface Then  
                Dim types As New List(Of Type)()  
                AddInterface(types, type)  
                Return types  
            End If  
            Return SelfAndBaseClasses(type)  
        End Function  
 
        Private Shared Function SelfAndBaseClasses(ByVal type As Type) As IEnumerable(Of Type)  
            While type IsNot Nothing  
                Return New Type() {type}  
                typetype = type.BaseType  
            End While  
        End Function  
 
        Private Shared Sub AddInterface(ByVal types As List(Of Type), ByVal type As Type)  
            If Not types.Contains(type) Then  
                types.Add(type)  
                For Each t As Type In type.GetInterfaces()  
                    AddInterface(types, t)  
                Next  
            End If  
        End Sub  
 
        Private Class MethodData  
            Public MethodBase As MethodBase  
            Public Parameters As ParameterInfo()  
            Public Args As Expression()  
        End Class  
 
        Private Function FindBestMethod(ByVal methods As IEnumerable(Of MethodBase), ByVal args As Expression(), ByVal method As MethodBase) As Integer  
            Dim applicable As MethodData() = methods.[Select](Function(m) New MethodData() With { _  
              .MethodBase = m, _  
              .Parameters = m.GetParameters() _  
            }).Where(Function(m) IsApplicable(m, args)).ToArray()  
            If applicable.Length > 1 Then  
                applicableapplicable = applicable.Where(Function(m) applicable.All(Function(n) m.Equals(n) OrElse IsBetterThan(args, m, n))).ToArray()  
            End If  
            If applicable.Length = 1 Then  
                Dim md As MethodData = applicable(0)  
                For i As Integer = 0 To args.Length - 1  
                    args(i) = md.Args(i)  
                Next  
                method = md.MethodBase  
            Else  
                method = Nothing 
            End If  
            Return applicable.Length  
        End Function  
 
        Private Function IsApplicable(ByVal method As MethodData, ByVal args As Expression()) As Boolean  
            If method.Parameters.Length <> args.Length Then  
                Return False  
            End If  
            Dim promotedArgs As Expression() = New Expression(args.Length - 1) {}  
            For i As Integer = 0 To args.Length - 1  
                Dim pi As ParameterInfo = method.Parameters(i)  
                If pi.IsOut Then  
                    Return False  
                End If  
                Dim promoted As Expression = PromoteExpression(args(i), pi.ParameterType, False)  
                If promoted Is Nothing Then  
                    Return False  
                End If  
                promotedArgs(i) = promoted  
            Next  
            method.Args = promotedArgs 
            Return True  
        End Function  
 
        Private Function PromoteExpression(ByVal expr As Expression, ByVal type__1 As Type, ByVal exact As Boolean) As Expression  
            If expr.Type.Equals(type__1) Then  
                Return expr  
            End If  
            If TypeOf expr Is ConstantExpression Then  
                Dim ce As ConstantExpression = DirectCast(expr, ConstantExpression)  
                If ce.Equals(nullLiteral) Then  
                    If Not type__1.IsValueType OrElse IsNullableType(type__1) Then  
                        Return Expression.Constant(Nothing, type__1)  
                    End If  
                Else  
                    Dim text As String  
                    If literals.TryGetValue(ce, text) Then  
                        Dim target As Type = GetNonNullableType(type__1)  
                        Dim value As [Object] = Nothing  
                        Select Case Type.GetTypeCode(ce.Type)  
                            Case TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64  
                                value = ParseNumber(text, target)  
                                Exit Select  
                            Case TypeCode.[Double]  
                                If target Is GetType(Decimal) Then  
                                    value = ParseNumber(text, target)  
                                End If  
                                Exit Select  
                            Case TypeCode.[String]  
                                value = ParseEnum(text, target)  
                                Exit Select  
                        End Select  
                        If value IsNot Nothing Then  
                            Return Expression.Constant(value, type__1)  
                        End If  
                    End If  
                End If  
            End If  
            If IsCompatibleWith(expr.Type, type__1) Then  
                If type__1.IsValueType OrElse exact Then  
                    Return Expression.Convert(expr, type__1)  
                End If  
                Return expr  
            End If  
            Return Nothing  
        End Function  
 
        Private Shared Function ParseNumber(ByVal text As String, ByVal type__1 As Type) As Object  
            Select Case Type.GetTypeCode(GetNonNullableType(type__1))  
                Case TypeCode.[SByte]  
                    Dim sb As SByte  
                    If SByte.TryParse(text, sb) Then  
                        Return sb  
                    End If  
                    Exit Select  
                Case TypeCode.[Byte]  
                    Dim b As Byte  
                    If Byte.TryParse(text, b) Then  
                        Return b  
                    End If  
                    Exit Select  
                Case TypeCode.Int16  
                    Dim s As Short  
                    If Short.TryParse(text, s) Then  
                        Return s  
                    End If  
                    Exit Select  
                Case TypeCode.UInt16  
                    Dim us As UShort  
                    If UShort.TryParse(text, us) Then  
                        Return us  
                    End If  
                    Exit Select  
                Case TypeCode.Int32  
                    Dim i As Integer  
                    If Integer.TryParse(text, i) Then  
                        Return i  
                    End If  
                    Exit Select  
                Case TypeCode.UInt32  
                    Dim ui As UInteger  
                    If UInteger.TryParse(text, ui) Then  
                        Return ui  
                    End If  
                    Exit Select  
                Case TypeCode.Int64  
                    Dim l As Long  
                    If Long.TryParse(text, l) Then  
                        Return l  
                    End If  
                    Exit Select  
                Case TypeCode.UInt64  
                    Dim ul As ULong  
                    If ULong.TryParse(text, ul) Then  
                        Return ul  
                    End If  
                    Exit Select  
                Case TypeCode.[Single]  
                    Dim f As Single  
                    If Single.TryParse(text, f) Then  
                        Return f  
                    End If  
                    Exit Select  
                Case TypeCode.[Double]  
                    Dim d As Double  
                    If Double.TryParse(text, d) Then  
                        Return d  
                    End If  
                    Exit Select  
                Case TypeCode.[Decimal]  
                    Dim e As Decimal  
                    If Decimal.TryParse(text, e) Then  
                        Return e  
                    End If  
                    Exit Select  
            End Select  
            Return Nothing  
        End Function  
 
        Private Shared Function ParseEnum(ByVal name As String, ByVal type__1 As Type) As Object  
            If type__1.IsEnum Then  
                Dim memberInfos As MemberInfo() = type__1.FindMembers(MemberTypes.Field, BindingFlags.[Public] Or BindingFlags.DeclaredOnly Or BindingFlags.[Static], Type.FilterNameIgnoreCase, name)  
                If memberInfos.Length <> 0 Then  
                    Return DirectCast(memberInfos(0), FieldInfo).GetValue(Nothing)  
                End If  
            End If  
            Return Nothing  
        End Function  
 
        Private Shared Function IsCompatibleWith(ByVal source As Type, ByVal target As Type) As Boolean  
            If source Is target Then  
                Return True  
            End If  
            If Not target.IsValueType Then  
                Return target.IsAssignableFrom(source)  
            End If  
            Dim st As Type = GetNonNullableType(source)  
            Dim tt As Type = GetNonNullableType(target)  
            If st IsNot source AndAlso tt Is target Then  
                Return False  
            End If  
            Dim sc As TypeCode = If(st.IsEnum, TypeCode.[Object], Type.GetTypeCode(st))  
            Dim tc As TypeCode = If(tt.IsEnum, TypeCode.[Object], Type.GetTypeCode(tt))  
            Select Case sc  
                Case TypeCode.[SByte]  
                    Select Case tc  
                        Case TypeCode.[SByte], TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], _  
                         TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.[Byte]  
                    Select Case tc  
                        Case TypeCode.[Byte], TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, _  
                         TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int16  
                    Select Case tc  
                        Case TypeCode.Int16, TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt16  
                    Select Case tc  
                        Case TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.[Single], _  
                         TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int32  
                    Select Case tc  
                        Case TypeCode.Int32, TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt32  
                    Select Case tc  
                        Case TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.Int64  
                    Select Case tc  
                        Case TypeCode.Int64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.UInt64  
                    Select Case tc  
                        Case TypeCode.UInt64, TypeCode.[Single], TypeCode.[Double], TypeCode.[Decimal]  
                            Return True  
                    End Select  
                    Exit Select  
                Case TypeCode.[Single]  
                    Select Case tc  
                        Case TypeCode.[Single], TypeCode.[Double]  
                            Return True  
                    End Select  
                    Exit Select  
                Case Else  
                    If st Is tt Then  
                        Return True  
                    End If  
                    Exit Select  
            End Select  
            Return False  
        End Function  
 
        Private Shared Function IsBetterThan(ByVal args As Expression(), ByVal m1 As MethodData, ByVal m2 As MethodData) As Boolean  
            Dim better As Boolean = False 
            For i As Integer = 0 To args.Length - 1  
                Dim c As Integer = CompareConversions(args(i).Type, m1.Parameters(i).ParameterType, m2.Parameters(i).ParameterType)  
                If c < 0 Then  
                    Return False  
                End If  
                If c > 0 Then  
                    better = True 
                End If  
            Next  
            Return better  
        End Function  
 
        ' Return 1 if s -> t1 is a better conversion than s -> t2  
        ' Return -1 if s -> t2 is a better conversion than s -> t1  
        ' Return 0 if neither conversion is better  
        Private Shared Function CompareConversions(ByVal s As Type, ByVal t1 As Type, ByVal t2 As Type) As Integer  
            If t1 Is t2 Then  
                Return 0  
            End If  
            If s Is t1 Then  
                Return 1  
            End If  
            If s Is t2 Then  
                Return -1  
            End If  
            Dim t1t2 As Boolean = IsCompatibleWith(t1, t2)  
            Dim t2t1 As Boolean = IsCompatibleWith(t2, t1)  
            If t1t2 AndAlso Not t2t1 Then  
                Return 1  
            End If  
            If t2t1 AndAlso Not t1t2 Then  
                Return -1  
            End If  
            If IsSignedIntegralType(t1) AndAlso IsUnsignedIntegralType(t2) Then  
                Return 1  
            End If  
            If IsSignedIntegralType(t2) AndAlso IsUnsignedIntegralType(t1) Then  
                Return -1  
            End If  
            Return 0  
        End Function  
 
        Private Function GenerateEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.Equal(left, right)  
        End Function  
 
        Private Function GenerateNotEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.NotEqual(left, right)  
        End Function  
 
        Private Function GenerateGreaterThan(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.GreaterThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.GreaterThan(left, right)  
        End Function  
 
        Private Function GenerateGreaterThanEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.GreaterThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.GreaterThanOrEqual(left, right)  
        End Function  
 
        Private Function GenerateLessThan(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.LessThan(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.LessThan(left, right)  
        End Function  
 
        Private Function GenerateLessThanEqual(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) Then  
                Return Expression.LessThanOrEqual(GenerateStaticMethodCall("Compare", left, right), Expression.Constant(0))  
            End If  
            Return Expression.LessThanOrEqual(left, right)  
        End Function  
 
        Private Function GenerateAdd(ByVal left As Expression, ByVal right As Expression) As Expression  
            If left.Type.Equals(GetType(String)) AndAlso right.Type.Equals(GetType(String)) Then  
                Return GenerateStaticMethodCall("Concat", left, right)  
            End If  
            Return Expression.Add(left, right)  
        End Function  
 
        Private Function GenerateSubtract(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.Subtract(left, right)  
        End Function  
 
        Private Function GenerateStringConcat(ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.[Call](Nothing, GetType(String).GetMethod("Concat", New Object() {GetType(Object), GetType(Object)}), New Object() {left, right})  
        End Function  
 
        Private Function GetStaticMethod(ByVal methodName As String, ByVal left As Expression, ByVal right As Expression) As MethodInfo  
            Return left.Type.GetMethod(methodName, New Object() {left.Type, right.Type})  
        End Function  
 
        Private Function GenerateStaticMethodCall(ByVal methodName As String, ByVal left As Expression, ByVal right As Expression) As Expression  
            Return Expression.[Call](Nothing, GetStaticMethod(methodName, left, right), New Object() {left, right})  
        End Function  
 
        Private Sub SetTextPos(ByVal pos As Integer)  
            textPos = pos 
            ch = If(textPos < textLen, text(textPos), ControlChars.NullChar)  
        End Sub  
 
        Private Sub NextChar()  
            If textPos < textLen Then  
                textPos += 1  
            End If  
            ch = If(textPos < textLen, text(textPos), ControlChars.NullChar)  
        End Sub  
 
        Private Sub NextToken()  
            While [Char].IsWhiteSpace(ch)  
                NextChar()  
            End While  
            Dim t As TokenId  
            Dim tokenPos As Integer = textPos 
            Select Case ch  
                Case "!"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.ExclamationEqual  
                    Else  
                        t = TokenId.Exclamation  
                    End If  
                    Exit Select  
                Case "%"c  
                    NextChar()  
                    t = TokenId.Percent  
                    Exit Select  
                Case "&"c  
                    NextChar()  
                    If cch = "&"c Then  
                        NextChar()  
                        t = TokenId.DoubleAmphersand  
                    Else  
                        t = TokenId.Amphersand  
                    End If  
                    Exit Select  
                Case "("c  
                    NextChar()  
                    t = TokenId.OpenParen  
                    Exit Select  
                Case ")"c  
                    NextChar()  
                    t = TokenId.CloseParen  
                    Exit Select  
                Case "*"c  
                    NextChar()  
                    t = TokenId.Asterisk  
                    Exit Select  
                Case "+"c  
                    NextChar()  
                    t = TokenId.Plus  
                    Exit Select  
                Case ","c  
                    NextChar()  
                    t = TokenId.Comma  
                    Exit Select  
                Case "-"c  
                    NextChar()  
                    t = TokenId.Minus  
                    Exit Select  
                Case "."c  
                    NextChar()  
                    t = TokenId.Dot  
                    Exit Select  
                Case "/"c  
                    NextChar()  
                    t = TokenId.Slash  
                    Exit Select  
                Case ":"c  
                    NextChar()  
                    t = TokenId.Colon  
                    Exit Select  
                Case "<"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.LessThanEqual  
                    ElseIf cch = ">"c Then  
                        NextChar()  
                        t = TokenId.LessGreater  
                    Else  
                        t = TokenId.LessThan  
                    End If  
                    Exit Select  
                Case "="c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.DoubleEqual  
                    Else  
                        t = TokenId.Equal  
                    End If  
                    Exit Select  
                Case ">"c  
                    NextChar()  
                    If cch = "="c Then  
                        NextChar()  
                        t = TokenId.GreaterThanEqual  
                    Else  
                        t = TokenId.GreaterThan  
                    End If  
                    Exit Select  
                Case "?"c  
                    NextChar()  
                    t = TokenId.Question  
                    Exit Select  
                Case "["c  
                    NextChar()  
                    t = TokenId.OpenBracket  
                    Exit Select  
                Case "]"c  
                    NextChar()  
                    t = TokenId.CloseBracket  
                    Exit Select  
                Case "|"c  
                    NextChar()  
                    If cch = "|"c Then  
                        NextChar()  
                        t = TokenId.DoubleBar  
                    Else  
                        t = TokenId.Bar  
                    End If  
                    Exit Select  
                Case """"c, "'"c  
                    Dim quote As Char = ch 
                    Do  
                        NextChar()  
                        While textPos < textLen AndAlso ch <> quote  
                            NextChar()  
                        End While  
                        If textPos = textLen Then  
                            Throw ParseError(textPos, Res.UnterminatedStringLiteral)  
                        End If  
                        NextChar()  
                    Loop While ch = quote 
                    t = TokenId.StringLiteral  
                    Exit Select  
                Case Else  
                    If [Char].IsLetter(ch) OrElse cch = "@"c OrElse cch = "_"c Then  
                        Do  
                            NextChar()  
                        Loop While [Char].IsLetterOrDigit(ch) OrElse cch = "_"c  
                        t = TokenId.Identifier  
                        Exit Select  
                    End If  
                    If [Char].IsDigit(ch) Then  
                        t = TokenId.IntegerLiteral  
                        Do  
                            NextChar()  
                        Loop While [Char].IsDigit(ch)  
      &nbs