Как мне перевести этот код в дерево выражений? - PullRequest
1 голос
/ 12 февраля 2010

У меня есть метод хеширования, операции которого зависят от ввода в функцию. Профилирование программы показало, что слишком много времени тратится на оценку этого метода хеширования. Я хочу попробовать изменить его в дерево выражений, чтобы проверки внутреннего цикла можно было выполнить один раз. Надеюсь, это будет быстрее, но я все равно узнаю о деревьях выражений.

Вот упрощенная версия функции (я отменил несколько очевидных оптимизаций для примера и убрал любую проверку ввода):

Private Function Checksum(ByVal inputValues As IEnumerable(Of UInt32),
                          ByVal declarations As IEnumerable(Of String),
                          ByVal statements As IEnumerable(Of String)) As UInt32
    Dim variables = New Dictionary(Of Char, UInt32)

    For Each declaration In declarations
        'parse declaration (eg. "X=52")'
        variables(declaration(0)) = UInt32.Parse(declaration.Substring(2))
    Next declaration

    For Each value In inputValues
        '"I"nput'
        variables("I"c) = value

        For Each statement In statements
            'parse statement (eg. "X=Y+Z")'
            Dim varResult = statement(0)
            Dim valueLeft = variables(statement(2))
            Dim operand = statement(3)
            Dim valueRight = variables(statement(4))

            'execute statement'
            Dim valueResult As UInt32
            Select Case operand
                Case "+"c : valueResult = valueLeft + valueRight
                Case "-"c : valueResult = valueLeft - valueRight
                Case "*"c : valueResult = valueLeft * valueRight
                Case "&"c : valueResult = valueLeft And valueRight
                Case "|"c : valueResult = valueLeft Or valueRight
                Case "^"c : valueResult = valueLeft Xor valueRight
            End Select
            variables(varResult) = valueResult
        Next statement
    Next value

    '"O"utput'
    Return variables("O"c)
End Function

Я хочу создать функцию, которая принимает объявления и операторы и выводит специализированное дерево выражений, представляющее функцию, которая принимает IEnumerable из UInt32 и возвращает UInt32.


Follow-Up:

Мне удалось, и ускорение было смешным (на порядок). Главные вещи, которые мне пришлось узнать, где:

  • Используйте Expression.Lambda и Expression.Compile, чтобы получить делегата, которого вы действительно можете использовать.
  • У метода фабрики Expression.Block есть параметр 'variable', который вы (по сути) используете для объявления локальных объектов. Аналогично, Expression.lambda имеет «параметры».
  • Если вы вызываете Expression.Parameter дважды, вы имеете дело с двумя разными переменными (даже если их имя одинаковое)! Сохраните результат для последующего использования. То же самое для этикеток и т. Д.
  • Результатом выражения BlockExpression является последнее выражение в блоке.

1 Ответ

2 голосов
/ 12 февраля 2010

Произошло обновление документации с VS 2010 RC. Я добавил несколько примеров нового ET API здесь: http://msdn.microsoft.com/en-us/library/bb397951(VS.100).aspx Он показывает, как создавать локальные переменные и как выполнять деревья выражений. Примеры есть как на VB, так и на C #.

Но, честно говоря, я все еще не понимаю, что вы пытаетесь сделать. Почему ваши декларации и заявления представляются в виде строк? И эта функция OpToExp также для меня загадка. Как вам удалось получить операнды как выражения, а оператор (который вы почему-то называете «операндом») как char? Если вы предоставите больше информации о том, что вы пытаетесь сделать, и об общем дизайне вашей системы, я могу вам помочь.

...