Здравствуйте, Sinclair, Вы писали:
S>Отлично. Попробовал. Есть ощущение, что возвёрнутые значения дальше не трансформируются. Т.е. трансформация работает только снизу вверх.
Ну, то есть как это работает: допустим, у меня есть таблица для некоторых ParameterExpression, которая задаёт их пределы.
Типа
{minA} <= {a} <= {maxA}.
Теперь у меня есть выражение типа
(a + 1 > 0).
Я пытаюсь его свернуть. Как это делается?
При помощи правила, которое сопоставляет выражениям вида
{a} > e вот такую кракозяблу
(({a} > e) || (minA > e)) && (maxA > e)). (1)
Перед этим надо превратить
(a + 1 > 0) в
(a > -1). (2)
Но вот у меня правило, которое вызвалось на выражении LessThan(Add(var e, Constant(int x))), Constant(int y)), вернуло оно (a > -1) и всё, поезд ушёл. Трансформатор поехал выше.
Допустим, я запихал правило 2 в первую фазу, а правило 1 — во вторую фазу трансформации.
Теперь, скажем, когда у нас в качестве minA указан {0}, а maxA — {h}, мы получаем
(({a} > {-1}) || ({0} > {-1})) && ({h} > {-1}))
Тут надо заново начинать трансформацию, т.к.
{0} > {-1} => {true},
({a} > {-1}) || {true})=>{true},
{true} && ({h} > {-1}) => ({h} > {-1}). Ок, это у нас была фаза трансформации №3 — свёртка AndAlso и OrElse с конст-аргументами.
Но теперь, получается, надо заново применять вторую фазу, т.к. из той же таблицы фактов мы знаем, что {h} >= {0}, и мы должны свернуть выражение в {true}.
Итого — либо мы гоняем цикл
expr = expr.TransformEx(FoldConstants);
expr = expr.TransformEx(FoldRanges);
до достижения стационарного состояния, либо в правиле свёртки диапазонов надо возвращать не AndAlso, а AndAlso(...).TransformEx(...).