From Novosibirsk, Russia? Our tiny company is looking for current or future rock-star developers.

April 24, 2008

Измеряем интеллигентность

Терпимость (как правило) характерна для людей средней интеллигентности. Люди менее образованные (обычно) боятся отличаться, а более интеллигентные (часто) считают, что те, кто от них отличается, неправы.

April 19, 2008

Крокодилы — это наше всё

Спецификация дизайна, разработанного сегодня с dottedmag'ом. (Начало опущено, ибо скучное.)

3.2. …Назовем такую последовательность Большим Красным Попугаем (Big Red Parrot, BRP), а каждый элемент ее несокращенной записи (например, bar:12) назовем Куском Мяса (Piece of Flesh, PoF).

4. Большой красный попугай — мысленная концепция, она слишком длинная и дорогая, чтобы быть примененной в реальном анализе. Поэтому нам необходимо ввести Маленького Зеленого Крокодила (Little Green Crocodile, LGC). Но перед этим отметим важный факт.

4.1. Большие красные попугаи линейно упорядоченны.

4.2. Маленький зеленый крокодил — шаблон, соответствующий набору больших красных попугаев.

4.3 Взрослый (полностью построенный) маленький зеленый крокодил всегда начинается с обрубка хвоста (да, их купируют, как у спаниелей), обозначаемого звездочкой.

4.4. Пример крокодила — «* bar:15..21 (bar:22..bar:30 / bar:24)* foo:1..3».

4.5. После обрубка хваста идет набор кусков мяса, и/или диапазонов кусков мяса, и/или колец (которые он позаимствовал у удава).

4.6. Кусок мяса — это просто позиция в сорцах, например foo:5.

4.7. Диапазон кусков мяса — это два куска мяса, путь исполнения между которыми можно по ним однозначно (и быстро) определить. Будем писать foo:n..bar:m или же сокращенно foo:n..m. Что конкретно означает фраза «путь исполнения между которыми можно по ним однозначно (и быстро) определить», предстоит еще уточнить. (Например, это может означать, что оба куска мяса находятся в одной и той же функции, так что простым проходом исходного кода можно легко перечислить, что было между ними.) Совершенно точно, что между этими двумя кусками мяса может располагаться сложный цикл, так что под «быстро определить» понимается не перечисление всех Больших Красных Попугаев, а некое концептуальное понимание того, какие инструкции входят в диапазон.

4.8. Кольцо — это возможность неограченного числа повторений некоторой части крокодила, с остановкой на одном из кусков мяса, входящих в эту часть. Пример — «(bar:22..bar:30 / bar:24)*» (выполнено сколько угодно итераций цикла bar:22..bar:30, при этом на последней из них мы остановились на bar:24).

4.9. По мере развития теории крокодилов мы, возможно, выведем особей с другими разновидностями частей.

5. С маленькими зелеными крокодилами определено несколько фундаментальных операций.

5.1. Утолщение маленького зеленого крокодила относительно гоала X. Пусть голова (голова у крокодила справа) выглядит как foo:7..8. Пусть смежные с foo:7..8 строчки foo:5, foo:6, foo:9 и foo:10 не влияют на результат X. Тогда мы расширяем голову до foo:5..10.

5.2. Удлинение маленького зеленого крокодила. Пусть хвост (он слева) крокодила выглядит как bar:5. Тогда мы выясняем, откуда мы могли прийти к bar:5, и приписываем эту точки слева, получая что-то вроде «bar:4..5», а потом, по мере продолжения удлинения, «boz:88 bar:1..5».

5.3. Кормление маленького зеленого крокодила дописывает заданный кусок мяса справа, делая его новой головой.

5.4. Заднее попугаенье (backward parrotizing) маленького зеленого крокодила получает набор маленьких зеленых крокодилов, описывающий набор больших красных попугаев, исполняемых непосредственно перед большими красными попугаями, которых описывает исходный маленький зеленый крокодил.

5.5. Переднее попугаенье (forward parrotizing) маленького зеленого крокодила получает набор маленьких зеленых крокодилов, описывающий набор больших красных попугаев, исполняемых непосредственно после больших красных попугаев, которых описывает исходный маленький зеленый крокодил.

5.6. Крокодильчонок — это крокодил без обрубка хвоста. Купированием крокодильчонка получают взрослого маленького зеленого крокодила. Например, из «foo:7 bar:5..10» получается «* foo:7 bar:5..10». Во всём остальном крокодильчонки ведут себя также, как и взрослые крокодилы (что естественно, они же тоже крокодилы, только еще маленькие).

6. Крокодилы — это наше всё.

6.1. В анализе каждому construct'у соответствует кусок мяса, например, foo:7.

6.2. Первым делом из этого куска выращивают крокодильчонка (например, можно взять пустого крокодильчонка и накормить его этим куском). Получаем крокодильчока foo:7.

6.3. Далее мы выясняем, есть ли в кэше крокодилы, головна которых совпадает с нашим крокодильчонком. Если есть, мы удлиняем крокодильчонка до тех пор, пока он либо не совпадет с каким-то крокодилом из кэша (за исключением обрубка хвоста, разумеется), либо пока он не перестанет быть похожим на крокодилов их кэша.

6.4. Если крокодильчонок совпал с кем-то в кэше, то всё скучно, берем результат из кэша. Рассматриваем случай, когда он не совпал.

6.5. Теперь у гоала зовется preRun, и мы начинаем его реально вычислять. Пусть наш goal — «значение переменной Z». У нас есть несколько стратегий вычисления, которые могут быть выражены через операции с крокодилом.

6.6. Мы можем купировать крокодильчонка после первого же куска мяса, получив «* foo:7», выполнить поиск всех присваиваний переменной Z и соединив их результаты. Такой уровень точности анализа (grade) мы можем назвать NO_FLOW. Мы получим ответ (NO_FLOW: * foo:7 => A | B | C), который можно кэшировать.

6.7. Мы можем выполнять заднее попугаенье, по необходимости удлинняя крокодильчонка, в поисках присваиваний Z. Например, в момент, когда крокодильчонок станет bar:25..30 foo:1..7, мы можем встретить Z=42. Тогда мы запишем ответ (EXACT: bar:25..30 foo:1..7 => 42). С другой стороны, мы могли встретить присваивание Z=Y, и тогда мы бы продолжили искать значение Y с тем же крокодильчонком, который мог стать при этом еще длиннее, и в итоге закэшировали ответ вроде (EXACT: boz:15 bar:20..30 foo:1..7 => 24). [Хитрый реализационный момент — как удлиннять крокодильчонка, при этом для Y сделав вид, что его середина — это голова.]

6.8. Мы можем использовать эвристику, чтобы упростить крокодила перед записью в кэш. Например, циклы (повторяющиеся последовательности) можно заменять кольцами, если они не влияют на наш гоал (или если вляют не сильно, и мы хотим немного потерять точность анализа). Ясно, что чем более общего вида получится крокодил, тем полезнее будет кэш.

April 17, 2008

Scorpions в Новосибирске

Вернулся с концерта Scorpions в Новосибирске. Как всегда, понравилось, но средне (ибо я за хорошую акустику и отсутствие толпы с аплодисментами). Прозвучало:

Hour I (Humanity: Hour I, 2007);
Coming Home (Love at First Sting, 1984);
The Zoo (Animal Magnetism, 1980);
No Pain No Gain (Face The Heat, 1993);
Deep and Dark (Unbreakable, 2004);
Coast to Coast (Lovedrive, 1979); — спасибо Константину за «опознание» этой мелодии
Always Somewhere (Lovedrive, 1979);
Send Me An Angel (Crazy World, 1990);
You And I (Pure Instinct, 1996);
Living For Tomorrow (Still Loving You, 1992);
Hey You (Animal Magnetism, 1980);
321 (Humanity: Hour I, 2007);
Alien Nation (Face The Heat, 1993);
Dynamite (Blackout, 1982);
Blackout (Blackout, 1982);
Соло барабанщика;
Still Loving You (Love at First Sting, 1984);
Humanity (Humanity: Hour I, 2007);
Wind Of Change (Crazy World, 1990);
Rock You Like A Hurricate (Love at First Sting, 1984);
When The Smoke Is Going Down (Blackout, 1982);
A Moment In A Million Years (Eye II Eye, 1999).

Есть подозрение, что где-то в конце я пропустил Is There Anybody There (Still Loving You, 1992).