OSDev

для всех
Текущее время: 16 июл 2018, 07:42

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 285 ]  На страницу Пред.  1 ... 22, 23, 24, 25, 26, 27, 28, 29  След.
Автор Сообщение
СообщениеДобавлено: 15 фев 2015, 22:36 
Аватара пользователя

Зарегистрирован: 17 фев 2013, 16:13
Сообщения: 163
Есть извечная проблема, связанная с тем, на кого повесить ответственность за корректность использования некоторой функции. Речь идёт о написании некоторой стандартной библиотеки некоторого гипотетического языка.

Есть библиотека и клиентский код, который вызывает функцию библиотеки. Вопрос: кто проверяет корректность параметров функции? Сама функция или клиент?

С одной стороны, хочется, чтобы функция сама могла себя обезопасить, мало ли какой чайник её будет использовать. С другой стороны, проверка параметров может сильно (даже СИЛЬНО) замедлить функцию, которая сама по себе не очень сложная, но вызывается несколько миллиардов раз (и такое бывает). По идее, профессионал будет использовать функцию аккуратно и проверки ему не нужны.

Я прихожу к выводу, что правильнее всего проверки делать на стороне библиотеки в виде опции. Есть некий checkLevel, который можно указывать до компиляции. Чем выше checkLevel, тем больше проверок выполняется при вызове функции. Когда программист убедился, что всё в порядке, ставится checkLevel=0 и программа запускается для своей основной работы. Заметьте, что это не то же самое, что debug/release. В debug у нас идёт компиляция без оптимизации, а нам нужен release, но с проверкой корректности вызова функций.

Почему я не иду по очевидному пути повесить всё на клиента? Во-первых, как меня учили: клиент всегда тупой (полу-шутка). Во-вторых, создатель библиотеки лучше знает, в каком диапазоне должны быть параметры и знает прочие тонкости её работы, негоже заставлять клиента глубоко вникать в эти параметры, чтобы гарантированно правильно осуществить проверку. Клиент – не автор библиотеки и не обязан компетентно отслеживать все случаи, хотя никто ему не запрещает пробовать. В-третьих, если библиотека меняется, могут меняться правила, определяющие корректность параметров. Соответственно, автор изменений вносит изменения и в проверку параметров. Короче говоря, клиент может случайно совершить ошибку куда быстрее, если особенности использования функции довольно сложны, а потому автор функции должен её правильно обезопасить.

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

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

Аналогично тому, о чём я говорил ранее: у каждой "долгоиграющей" функции должен быть свой уровень вывода промежуточной или отладочной информации о своей работе.

О чём я вообще говорю? Стандартная библиотека языка обязана быть эффективной. Я не раз сталкивался с необходимостью самостоятельно реализовывать тот или иной алгоритм из-за того лишь только, что в доступной мне библиотеке он был написан либо пьяным индусом, либо профессионально, но со всеми проверками на дурака, которые нафиг мне не нужны (не нужны были в том возрасте).

Есть у кого-либо идеи на этот счёт?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 15 фев 2015, 23:01 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1089
Цитата:
Есть библиотека и клиентский код, который вызывает функцию библиотеки. Вопрос: кто проверяет корректность параметров функции? Сама функция или клиент?

Есть понятие устойчивости. Так вот если нужна устойчивость к ошибкам. А она как правила нужна то функция должна позаботиться обетом сама. Но не везде она нужна.

Цитата:
С одной стороны, хочется, чтобы функция сама могла себя обезопасить, мало ли какой чайник её будет использовать. С другой стороны, проверка параметров может сильно (даже СИЛЬНО) замедлить функцию, которая сама по себе не очень сложная, но вызывается несколько миллиардов раз (и такое бывает). По идее, профессионал будет использовать функцию аккуратно и проверки ему не нужны.

Ага профессионалы как раз и ошибаются чаще всего. Лично я в последнее время пишу 2 функции.
С приставкой Base без проверок. И все проверки в отдельную функцию.
А вообще по идее это должен решать оптимизатор где проверки нужны, а где нет.

Цитата:
Соответственно, автор изменений вносит изменения и в проверку параметров. Короче говоря, клиент может случайно совершить ошибку куда быстрее, если особенности использования функции довольно сложны, а потому автор функции должен её правильно обезопасить.

Скорее всего функция спроектирована неправильно. И её лучше разделить на несколько которые можно вызывать последовательно.
Либо инкапсулировать параметры в объект. Где можно и абстрагировать и сделать сокрытие что обеспечит проверку и независимость входных параметров.


Цитата:
О чём я вообще говорю? Стандартная библиотека языка обязана быть эффективной. Я не раз сталкивался с необходимостью самостоятельно реализовывать тот или иной алгоритм из-за того лишь только, что в доступной мне библиотеке он был написан либо пьяным индусом, либо профессионально, но со всеми проверками на дурака, которые нафиг мне не нужны (не нужны были в том возрасте).

Знал бы где упадёшь соломы насыпал бы, да газетку подстелил.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 01:23 
Аватара пользователя

Зарегистрирован: 28 май 2012, 23:44
Сообщения: 237
Откуда: Санкт-Петербург
Yoda писал(а):
характеристики компилятора сейчас не сильно связаны со средой разработки. Связь компилятора со средой прошла ряд фаз. С одной стороны, качество компиляции раньше было ограничено скоростью работы машины, сейчас этот фактор уже не играет определяющей роли.

Мои слова про плохую оптимизацию и недоработки в компиляторах RAD -- камень в огород Delphi и Visual Basic. VB, правда, перешел на платформу .NET и теперь критикуется по другой статье, а претензии к Delphi в большинстве своем актуальны.

C IDE связана другая догма, которую тоже можно включить в список:
  • Компилятор -- законченный монолит, включающий в себя лексический и семантический анализаторы, кодогенератор и всё остальное. Если, например, нужна подсветка синтаксиса или подсказки в IDE, соответствующую инфраструктуру придется реализовывать самостоятельно.
В результате получается, что любая более-менее развитая среда содержит в себе несколько лексических анализаторов, библиотек для построения зависимостей кода, чтения инфы для подсказок в редакторе и т. п. Всё это нужно согласовано поддерживать, следить за нововведениями синтаксиса и всё такое прочее. А разработчики компилятора -- бравые ребята, они недосягаемы, ибо не барское это дело -- предоставлять инфраструктуру для каких-то там IDE...

В развитых инфраструктурах вроде .NET или Java уже есть все нужные инструменты, бери и пользуйся. Тем не менее, проблема многократного дублирования сущностей никуда не девается. Дьявол, как известно, в деталях, и при использовании непременно вылезет. Если кто пользовался, отпишитесь.

Мне кажется, что если уж разрабатывать компилятор, нужно делать не монолит, а набор модулей, на этапе проектирования предуматривая существование таких инструментов как IDE, статический анализатор кода и др. Делать вид, что таких инструментов не существует, или что они появятся по волшебству, или что потом как-нибудь, авось, -- глупо.

Yoda писал(а):
Вот эта ситуация также иногда вводит меня в состояние ступора. Скачиваешь проект, - и не можешь его скомпилировать, - надо целиком ставить последнюю версию студии и импортировать туда проект. Или (для Linux-овых проектов) запускаешь конфигуратор, который ругается на кучу отсутствующих инструментов (всякие скриптовые интерпретаторы-генераторы), устанавливаешь инструменты, а результата всё равно нет по причинам, известным одному лишь Торвальдсу.

Да-да, часть магии может быть сделана на Tcl, другая на Lua, а какая-то незначащая фигня может запросить себе Perl. Жуть! Не знаю, уместно ли тут снова рекламировать Кантор...

Yoda писал(а):
Нет, объём кода здесь ни при чём. Два подхода отличаются по самой своей сути, по логике мышления. Вот они:
Императивный: "У нас что-то есть. Что мы из этого можем получить?"
Функциональный: "Нам что-то нужно. Что нам нужно, чтобы это получить?"

Я, похоже, нашел догму ФП, спасибо нашей дискуссии:
  • В компилируемом функциональном языке -- неочевидная кодогенерация.
Если в императивном языке при известной сноровке более-менее можно представить, в какие машинные инструкции будет скомпилирован код, то во что превратится ФП-код -- фиг его знает. Где какие библиотечные функции будут вызваны, где магия компилятора, как на нее положительно повлиять в целях увеличения быстродействия или объема сгенерированного кода? Возможно, это тоже дело сноровки, не знаю. Мне кажется, что функциональные языки пока не достигли нужного уровня предсказуемости, пока лишь идет их становление, если оно вообще идет.

Между тем, в самом распространенном функциональном языке проблема очевидности и предсказуемости давно решена, решение достаточно лишь позаимствовать. Загвоздка лишь в том, что многие отказывают SQL в праве считаться ФП-языком. :)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 12:20 
Аватара пользователя

Зарегистрирован: 14 мар 2011, 12:31
Сообщения: 944
Откуда: Дагоба
Freeman писал(а):
Если, например, нужна подсветка синтаксиса или подсказки в IDE, соответствующую инфраструктуру придется реализовывать самостоятельно.

Вот тем мне и нравятся универсальные среды, что они легко настраиваются. В UltraEdit я активно поправлял подсветку синтаксиса для C, C++, HTML, CSS, JS, т.к. в варианте "из коробки" много чего не учтено, и самостоятельно сделал подсветку синтаксиса для ассемблера и Verilog, т.к. они вообще не были предусмотрены. И отлично всё работает!

Freeman писал(а):
В результате получается, что любая более-менее развитая среда содержит в себе несколько лексических анализаторов

Надо заметить, что лексические анализаторы там сильно упрощённые и многих вещей не понимают (например, нельзя сделать подсветку raw strings или всегда корректно обрабатывать universal character names – последовательности вида \u1234). В упрощённом варианте (только для неполной подсветки синтаксиса) можно сделать более-менее универсальный сканер.

Freeman писал(а):
А разработчики компилятора -- бравые ребята, они недосягаемы, ибо не барское это дело -- предоставлять инфраструктуру для каких-то там IDE...

Я подозреваю, что они о таких вещах даже и не задумываются.

Freeman писал(а):
Мне кажется, что если уж разрабатывать компилятор, нужно делать не монолит, а набор модулей

Я уверен, что так и только так и нужно делать компиляторы. Как минимум должно быть деление на фронтенд/бэкенд.

Freeman писал(а):
Я, похоже, нашел догму ФП, спасибо нашей дискуссии:
  • В компилируемом функциональном языке -- неочевидная кодогенерация.

Она не то, чтобы неочевидная, её просто не существует в самой идее функциональных языков.

_________________
Yet Other Developer of Architecture.
The mistery of Yoda’s speech uncovered is:
Just an old Forth programmer Yoda was.

<<< OS Boot Tools. >>>


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 14:55 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1089
Yoda писал(а):
Freeman писал(а):
А разработчики компилятора -- бравые ребята, они недосягаемы, ибо не барское это дело -- предоставлять инфраструктуру для каких-то там IDE...

Я подозреваю, что они о таких вещах даже и не задумываются.

Так правильно это же не выгодно. А проблем больше чем в 10 раз в сравнении с разными лексическими анализаторами.


Yoda писал(а):
Freeman писал(а):
Мне кажется, что если уж разрабатывать компилятор, нужно делать не монолит, а набор модулей

Я уверен, что так и только так и нужно делать компиляторы. Как минимум должно быть деление на фронтенд/бэкенд.

Ага. В теории оно везде и поделено. А на практике нет. Если не брать в расчёт то что бешено возрастает пустой код. Раза в 2 точно. Только что-бы сделать абстрактные интерфейсы и связи между ними.
Все практики в один голос твердят что оптимизатору нужно знать исходную структуру. И оторвать его от грамматического парсера не получается.

Yoda писал(а):
Freeman писал(а):
Я, похоже, нашел догму ФП, спасибо нашей дискуссии:
  • В компилируемом функциональном языке -- неочевидная кодогенерация.

Она не то, чтобы неочевидная, её просто не существует в самой идее функциональных языков.

Да ладно её и в императивной то не всегда проследишь. Что такое стек я узнал лет через 5 после того как научился программировать.
and or xor - может выполнять ветвлением, а может битовой операцией.
Или взять к примеру шейдоры. Так один исходный код на целевой платформе не узнаваем в принципе.
case имеет несколько вариантов. Таблицей, в виде условий и ветвления. И в сжатом, оптимизированном виде.
А если ещё вспомнить что хитрый оптимизатор может изымать условие из цикла, т.е менять их вложенность.

Думаю стоит всё же говорить что современные языки это смесь 3 подходов императивного, функционального и декларативного.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 17:16 
Аватара пользователя

Зарегистрирован: 14 мар 2011, 12:31
Сообщения: 944
Откуда: Дагоба
pavia писал(а):
Ага. В теории оно везде и поделено. А на практике нет. Если не брать в расчёт то что бешено возрастает пустой код. Раза в 2 точно. Только что-бы сделать абстрактные интерфейсы и связи между ними.

В любом случае парсер передаёт результат своей работы, – AST (абстрактное синтаксическое дерево), – дальше по цепочке. Не вижу большой проблемы разделить компилятор на две части, оформить АПИ и описать структуру дерева разбора. Думаю, интерфейсы не сильно увеличат пустой код, зато бонус от такого разделения весьма ощутим – можно произвольно соединять между собой фронтенды, оптимизаторы и бэкенды, а для разработки нового языка фактически необходим только фронтенд. На самом деле нет необходимости создавать AST в формате, пригодном для сохранения в файл, типа объектника. Вполне достаточно просто держать его в памяти.

pavia писал(а):
Все практики в один голос твердят что оптимизатору нужно знать исходную структуру. И оторвать его от грамматического парсера не получается.

Вообще-то AST вполне хватает для всей дальнейшей работы. Если чего-то действительно нужно, можно предусмотреть соответствующие поля в узлах дерева для хранения дополнительных данных.

pavia писал(а):
Да ладно её и в императивной то не всегда проследишь. Что такое стек я узнал лет через 5 после того как научился программировать.
and or xor - может выполнять ветвлением, а может битовой операцией.

В машине Тьюринга стека вообще нет, однако она функционально эквивалентна любой другой реальной машине. Дело не в том, есть стек или нет и как именно отображаются операции из одного представления в другое, а в том, что представление о хранении и манипулировании данными изначально заложено в императивный подход (и в саму машину Тьюринга). А в функциональном представлении вообще нет такого понятия, как "хранение данных", а есть только отображение одних данных в другие при помощи функций. Как в математике, например, функция sin(x) не подразумевает вообще такого понятия, как "регистр", она лишь отображает одни значения на другие. Или, например, расчёт полинома x^4 + 2*x^3 + 3*x^2 + 4*x + 5 в функциональном представлении является всего лишь суперпозицией нескольких функций - умножения, сложения и возведения в степень, но хранения каких-либо данных и манипулирования ими нет.

_________________
Yet Other Developer of Architecture.
The mistery of Yoda’s speech uncovered is:
Just an old Forth programmer Yoda was.

<<< OS Boot Tools. >>>


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 19:00 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1061
Откуда: Балаково
Yoda писал(а):
Himik писал(а):
Надо различать примеры для обучения или для простого вычисления, и реальное программирование. В программировании используются схожие с ИП способы использования переменных для хранения промежуточных сумм

Я ведь говорю то же самое. Чистое ФП невозможно

На самом деле это касается декларативной парадигмы, которую используют в программировании на функциональных языках. Функциональный язык сам по себе это всего лишь инструмент, который можно использовать по всякому. Поэтому правильнее сказать - чистое декларативное программирование невозможно, или малоэффективно. Возможно, что в будущем изобретут умный оптимизатор, понимающий сложные формулы.
Yoda писал(а):
Однако, программа, которая не имеет побочных эффектов, бесполезна ((с) не помню кто), без "побочных эффектов" невозможен никакой ввод-вывод. Поэтому реальное ФП вынуждено добавлять средства ИП, чтобы не быть бесполезным.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 16 фев 2015, 23:29 
Аватара пользователя

Зарегистрирован: 14 мар 2011, 12:31
Сообщения: 944
Откуда: Дагоба
Himik писал(а):
Надо различать "ввод-вывод" и "побочный эффект". Ввод-вывод является интерфейсом любой функции.

Как вы опишете интерфейс функций printf и scanf? Что на что они отображают в функциональном смысле?

Himik писал(а):
При этом ввод идёт из-за пределов, и вывод идёт за пределы функции, поэтому это не влияет на внутреннюю работу самой функции - предсказуемость работы функции соблюдена.

Предсказуемость в функциональном смысле означает независимость результата от порядка вызова, и возврат одного и того же значения при передаче одних и тех же аргументов. Так, sin(pi/2) всегда вернёт 1, а sin(pi) всегда вернёт 0 независимо от порядка их вызова, включая одновременный вызов. Одинаков ли результат работы функции printf при перестановке двух вызовов? Можно ли одновременно запустить две функции printf? Возвращает ли функция scanf один и тот же результат будучи вызванной с одними и теми же аргументами?

Himik писал(а):
Вывод из программы - это и есть полезный результат.

С точки зрения ФП нет двух вещей - взаимодействия и состояния. Единственный способ ввода/вывода, который не нарушает парадигму ФП, это когда вся программа целиком рассматривается как единая функция, - принимает аргументы, возвращает результат и на этом завершает свою работу.

_________________
Yet Other Developer of Architecture.
The mistery of Yoda’s speech uncovered is:
Just an old Forth programmer Yoda was.

<<< OS Boot Tools. >>>


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 17 фев 2015, 01:46 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1061
Откуда: Балаково
Раз мы хотим забивать гвозди микроскопом, описывая задачи функциональным языком для машины Тьюринга, то должны учитывать принцип работы целевой машины, это обязательно. Вводу и выводу нужно давать какое-то определение в языке. Функции без параметров считаются вводом, а функции без возвращаемого значения являются выводом. Количество разных функций В/В в программе ни чем не ограничено, и вызываются они последовательно согласно коду программы. Сами printf и scanf могут быть Сишными функциями. А могут быть нативными функциями, но внутри использовать Сишные функции низкоуровневого обмена данными с консолью. Вообще надо изучать описания функциональных языков, чтобы детально узнать как это реализовано. В OCaml сделано просто, как я описал. В Haskell какая-то другая система ввода-вывода.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 17 фев 2015, 13:47 

Зарегистрирован: 15 фев 2015, 12:41
Сообщения: 9
Цитата:
Юрий Раньше доменное имя принадлежало «Оптимизирующим технологиям», 3 года назад они не продлили регистрацию, теперь это имя моё.
Цитата:
Yoda А вы сами не имеете к ним отношения? Весьма интересный проект.
Никакого отношения к ним не имею. Имел только одно отношение – недовольство, когда они зарегистрировали это домен на себя. Я его присматривал для себя, да как-то не торопился с регистрацией. Но они увели домен из-под носа. Соответственно отношение было такое: «Ах вы такие-сякие!». Но потом они не продлили регистрацию, и моё отношение к ним улучшилось :)
Цитата:
Zealint [ 15 ] :: Комментарии
бесит, когда нужно закомментировать большой блок кода (например, в процессе поиска трудноуловимой ошибки бинарным поиском), а в этом блоке уже несколько десятков маленьких блоков /* */. Приходится у каждого такого блока убирать закрывающий символ или добавлять один открывающий после. Такого не должно быть НИКОГДА.
Объяснение причин, почему обычные комментарии не могут быть вложенными, можно найти здесь: Комментарии. Если коротко, то объяснение такое:
Код:
/* начало комментария
   char  x[] = "*/";    // ошибка, начиная с «";»
конец комментария */
Такой код внутри комментария «ломает» этот комментарий. Чтобы правильно определить начало и конец всех вложенных комментариев, нужно проводить, как минимум, лексический анализ. Но комментарии – эта такая вещь, в которой этот анализ не проводится по определению. Даже если мы для «/*» будем искать соответствующую пару «*/», то эта пара может найтись где-нибудь в строковом литерале. Как преодолеть – предложение здесь: Нерабочий код.
Цитата:
Freeman Разделение битовых и логических операций -- одна из немногих вещей, сделанная в Си правильней Паскаля. Для разрешения неоднозначности в Паскале приходятся скобки ставить. Сравните с SQL, например, где битовых операций нет, поэтому and и or вполне работают и без скобок. Скобки -- снижение читабельности.
Yoda Совершенно верно.
В Си упомянутые операции расположены в таком порядке по приоритету: «&» «^» «|» «&&» «||» (чем левее, тем приоритетней). На практике битовые операции как-то редко соседствуют с логическими. Логические операции чаще соседствуют с операциями сравнения. Результаты битовых операций чаще потом используются для присваивания. Скобки снижают читаемость, но уменьшение числа операций, их «экономия» - тоже неплохой момент. Если запретить толковать целые числа как логические (false – это не 0, а bool(0)), то int & int -> int (битовая операция), а bool & bool -> bool (логическая операция). Отделение булевых от числовых типов имеет смысл, если операцией проверки на равенство является «==», а не «=». В случае if (a=b) вместо if (a==b) (где a и b – числовые) компилятор должен дать ошибку, т.к. ожидается булево значение, а не числовое.
Цитата:
Yoda Я бы повесился так писать. В соответствии со своей концепцией лаконичности я, наоборот, сделал для себя в С/С++ стандартные определения типов i8, i16, 132, i64, u8, u16, u32 и u64. Не буду утверждать, что это лучше чем int* и uint*, но мне удобно.
А мне удобнее i15 (со знаком), i16 (без знака), i31 (со знаком), i32 (без знака). Концепцию лаконичности полностью разделяю. С уточнением, что не в ущерб ясности.
Цитата:
Zealint [ 17 ] :: Оператор условия
Код:
if условие { }
else if условие { }
else { }
по сути ничем не отличается от
if условие { }
else {
  if условие { }
  else { }
}
и именно так и должно восприниматься компилятором. Создавать лишнее ключевое слово типа elif нет никакого смысла.

запретить нафиг блоки кода с одним оператором без указания скобок.
Я для себя выбрал такой синтаксис:
Код:
(if условие
   . . .
if ещё одно условие
   . . .
if третье условие
   . . .
else
   . . .
)
Второй и третий if – это elseif в иных языках программирования. И ключевое слово экономится, и все возможности предоставлены. Правда, есть сомнения, что это никого не запутает, что все всё поймут. Возможно, elseif (как ключевое слово) всё-таки лучше оставить.
Так же отпадает необходимость оформлять блоки кода фигурными скобками {}. В языке Rust как раз запретили употреблять if, else, for, while без этих скобок. В Rust операторы for (i=0;i<N;i++); и for (i=0;i<N;i++) …; – это ошибка.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 285 ]  На страницу Пред.  1 ... 22, 23, 24, 25, 26, 27, 28, 29  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: poly и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB