Препроцессор синтаксиса для FPC

Планы, идеология, архитектура и т.п.

Модератор: Модераторы

Препроцессор синтаксиса для FPC

Сообщение carrots » 13.09.2013 23:00:37

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

Меня часто радовало то что в паскале обязательно объявлять переменные в начале функции, это здорово помогает при ее переводе на ассемблер, но еще больше меня это раздражало, так как отнимает дополнительное время и вынуждает создавать кашу объявлений. Ориентироваться в таком коде сложнее, а не проще, потому я сделал возможность объявлять переменные по сишному, в любом месте.
Код: Выделить всё
string s := 'hello!!';
for int i := 0 to 100 do


Несколько лет назад я начал программировать языке python, к хорошему быстро привыкаешь... и естественно в паскале частые begin и end, постепенно начали казаться мусором, потому сделал чтоб do или then вместе с bigin и end можно было заменить просто двоеточием
Код: Выделить всё
    if pos < 0:
      f['experience']:= 0;
      f['premium_exp']:= Now + 7 days;
    else:
      spacecraft_presets['parentid'][nid] := pos;
      spacecraft_presets.Save;

    for i := 0 to 100:
      f+=1;
      hh+=i;

    Result := fs['level'];


Конечно-же иногда не достаточно операторов, и вообще в одних документах нужны одни операторы, а в других другие, потому сделал возможность положить в operators.ini указать какие у нас будут дополнительные операторы и какую функцию они будут вызывать.
Код: Выделить всё
|| COr
&& CAnd
== Equal
!= NotEqual
<| Less
|> Greater
<|= LessOrEqual
|>= GreaterOrEqual
from ItemsFrom
. join

ну и конечно-же их можно использовать в тех файлах которые лежат в одном директории с operators.ini
Код: Выделить всё
function GetShopItems(AVKUserId: int64): ansistring;
begin
  int uid:=vk_users['vk_userid'].ItemIndex(AVKUserId); // Определяем внутренний id игрока по vkid
  if uid < 0 then exit;                                // Если данного игрока в базе нет - выходим

  // В iUserModels записываем список моделей кораблей которые уже есть у играка
  TIntCol iUserModels := spacecraft_presets['modelid'].ItemsI(ids(spacecraft_presets['parentid'] == uId && spacecraft_presets['_del'] == 0));

  with SpacecraftShop do
  begin
    // в iCanBey составляем список пресетов кораблей на которые у ирока достаточно серебра, золота и опыта
    TBoolCol iCanBey := experiencePrice <|= vk_users['experience'][uid]
                      && silverPrice <|= vk_users['silver'][uid]
                      && goldenPrice <|= vk_users['gold'][uid];

    // формируем строку ответа, в цикле добавляем параметр каждого корабля из магазина
    int iLoop := 0;
    for spacecraft_presets.pos in shopItems:
      spacecrafts.pos := spacecraft_presets['modelid']; // Номер модели корабля
      boolean iBought := spacecrafts.pos in iUserModels;// в iBought определяем куплена-ли уже данная модель

      Result += spacecraft_presets.pos . ';'             // Номер пресета
              . (iCanBey[iLoop] and not iBought) . ';'   // Доступен-ли для покупки
              . spacecrafts['fraction'] . ';'            // фракция
              . experiencePrice[iLoop] . ';'             // Стоимость в опыте
              . silverPrice[iLoop] . ';'                 // Стоимость в серебре
              . goldenPrice[iLoop] . ';'                 // Стоимость в золоте
              . spacecrafts['maxspeed'] . ';'            // Максимальная скорость
              . spacecrafts['size'] . ';'                // Длина
              . spacecrafts['health'] . ';'              // Общее hp корабля
              . spacecrafts['shield_mod'] . ';'          // hp щита
              . iBought . ';'                            // Куплен
              . spacecraft_presets['title'] . ';'        // Название
              . spacecraft_presets['description'] . '~'; // Описание

      iLoop+=1;
  end;

end;


Ну да, еще иногда к какой-то величине нужно, например к времени нужно добавить какую-то величину, например время, чтоб лишний раз не считать можно сделать так предварительно задать константы юнитам времени
Код: Выделить всё
const
  Week = 7;
  Weeks = 7;
  Day = 1;
  Days = 1;
  Hour = Day/24;
  Minute = Hour/60;
  Second = Minute/60;
  MiliSecond = Second/1000;
  Hours = Day/24;
  Minutes = Hour/60;
  Seconds = Minute/60;
  MiliSeconds = Second/1000;

а потом писать так fDataTime += 1hour+23Minutes или fDataTime += 2 hourі + 1 Minute препроцессор сам перемножит
Код: Выделить всё
function Get_User_Info(AVkId: int64): ansistring;
begin
  with vk_users:
    pos:=vk_users['vk_userid'].ItemIndex(AVKId);

    if pos < 0:
      pos:=additem;
      f['template'] := 'vk_users';
      f['vk_userid'] := AVKId;
      f['level'] := 0;
      f['gold'] := 200;
      f['silver'] := 20000;
      f['experience']:= 0;
      f['premium_exp']:= Now + 7 weeks;
    else:
      Save;
      int nid := spacecraft_presets.addClone(16);
      spacecraft_presets['parentid'][nid] := pos;
      spacecraft_presets.Save;

    Result := fs['level']+';'
            + fs['gold']+';'
            + fs['silver']+';'
            + fs['experience']+';'
            +TimeToStr(fs['premium_exp']);
end;


Добавлено спустя 12 минут:
Вот собственно..
Данный вариант будет обрабатывать только те файлы, рядом с которыми в папке лежит operators.ini
Сам препроцессор нужно положить в одну папку с ppcx64 и в лазарусе указать его как компилятор или заменить fpc
Вложения
CPreProcessor.zip
(17.93 КБ) Скачиваний: 385
Аватара пользователя
carrots
постоялец
 
Сообщения: 138
Зарегистрирован: 28.03.2008 02:13:02

Re: Препроцессор синтаксиса для FPC

Сообщение Logo » 13.09.2013 23:41:49

Ну и зачем портить синтаксис Паскаля?
Объявлять переменные в где попало, это не достижение, а зло. По прошествии времени потом сам забываешь, где и, что понаобъявлял.

Хорош этот препроцесор если добавить нужные операторы, например, для работы напрямую с запросами SQL, ну и, если заказчик требует от тебя исходники и видно, что этот заказчик мутит, что-то. То ты ему чесно даешь заказ, даешь исходники, а препроцессор не даешь. Если заказчик чесно расчитался, то тогда и препроцессор можно отдать. :D
Logo
постоялец
 
Сообщения: 464
Зарегистрирован: 20.08.2008 01:00:47

Re: Препроцессор синтаксиса для FPC

Сообщение Mirage » 14.09.2013 12:18:14

Что-то я смысла некоторых нововведений не пойму:
Код: Выделить всё
TBoolCol iCanBey := experiencePrice <|= vk_users['experience'][uid]
                      && silverPrice <|= vk_users['silver'][uid]
                      && goldenPrice <|= vk_users['gold'][uid];

Здесь "<|=" вместо "<="?
А "&&" вместо "and"?
А зачем?
Mirage
энтузиаст
 
Сообщения: 880
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Препроцессор синтаксиса для FPC

Сообщение runewalsh » 14.09.2013 15:33:58

Лучше бы параметризованные макросы сделал, как в сишном, от них ввиду отсутствия шаблонов хотя бы реальная польза есть -.-
Их и сейчас можно эмулировать:
Код: Выделить всё
{$define uber_macro:=
begin
  write(_1 + _2(_3));
end
{$undef _1} {$undef _2} {$undef _3}}

{$define _1:=1.0} {$define _2:=cos} {$define _3:=Math.Pi} uber_macro;

но это многосимвольное извращение, хотелось бы более канонный вариант.
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 471
Зарегистрирован: 27.04.2010 00:15:25

Re: Препроцессор синтаксиса для FPC

Сообщение hinst » 14.09.2013 20:43:34

carrots Объявлять переменные в середине метода не нужно. Нужно делать чтобы все методы были максимум с пятью переменными. Если переменных больше, надо проводить рефакторинг и выносить часть метода в отдельный метод.
Конструкция with не нужна. Идею с операторами я вообще не понял. Не писать begin и end? Не думаю что это нужно.
runewalsh
Плохо что
1. Внутри тела макроса не будет подсветки синтаксиса, так как практически любой редактор воспримет это всё.... ну, без подсветки.
2. Если в экземпляре макроса будет синтаксическая ошибка, то узнать о ней может оказаться сложно, так как компилятор покажет в лучшем случае на uber_marco; (которое в самом конце у тебя стоит), а в худшем вообще покажет в не относящийся к ошибке кусок кода
Аватара пользователя
hinst
энтузиаст
 
Сообщения: 782
Зарегистрирован: 12.04.2008 18:32:38

Re: Препроцессор синтаксиса для FPC

Сообщение carrots » 17.09.2013 12:56:26

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


Mirage
Здесь "<|=" вместо "<="?
А "&&" вместо "and"?
А зачем?

freepascal не позволяет переобъявить логические операторы так чтоб они возвращали не болевые значения, а мне нужен в результате ответ с результатами сравнения всех элементов колонки, то есть свой тип.

runewalsh
Хорошая идея, когда-то я уже хотел такое написать, только представлял его немного по другому, этом не было так необходимо. Скорее всего я скоро добавлю такого рода макросы в данный препроцессор.
<{uber_macro:=
"begin
write($_1+$_2($_3));
end;"}>
------------------------------------------------------------------------------
<{ _1:=1.0; _2:=cos; _3:=Math.Pi; $uber_macro }>

Что касательно шаблонов - есть-же генерики и inc файлы...

Добавлено спустя 2 минуты 54 секунды:
hinst, Вам не нужна with в freepascal??....
а подсветку синтаксиса можно поправить...
Аватара пользователя
carrots
постоялец
 
Сообщения: 138
Зарегистрирован: 28.03.2008 02:13:02

Re: Препроцессор синтаксиса для FPC

Сообщение hinst » 17.09.2013 14:58:06

carrots насчёт with - нет, мне лично не нужно, и я никогда не пользуюсь. К тому же, встречался с такой неприятностью: в какой-нибудь объект вводят новое свойство типа Width в TRect, и в некоторых местах
Код: Выделить всё
with form do
  with rect do
    Width := Right;

- ну это к примеру. И если раньше в rect не было Width, то теперь есть, и будет делаться не то, что хотели

Подсветку можно сделать если залезть в исходники SynEdit от лазаруса, а так же в исходники любого другого редактора текста, ну там Notepad++ или кто чем пользуется, а это может быть проблематично
И в лазарусе если начать писать без begin и end, автодополнение идентификаторов работать не будет
И если кто-нибудь пользуется для документации какой-нибудь штукой типа pasdoc, то тоже будет всё очень плохо, и придётся тоже подправлять
Последний раз редактировалось hinst 17.09.2013 15:00:09, всего редактировалось 1 раз.
Аватара пользователя
hinst
энтузиаст
 
Сообщения: 782
Зарегистрирован: 12.04.2008 18:32:38

Re: Препроцессор синтаксиса для FPC

Сообщение vada » 17.09.2013 14:59:28

Не понимаю, зачем писать на паскале? Пишите на С. Там препроцессор со своими попугаями прямо из коробки.
Нравится паскалевский синтаксис, можно своий хидер сделать с нужными словами и вперед. Уже где-то терли эту тему.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Препроцессор синтаксиса для FPC

Сообщение hinst » 17.09.2013 15:01:01

vada в C есть всякие другие неприятности и нехорошие вещи
Аватара пользователя
hinst
энтузиаст
 
Сообщения: 782
Зарегистрирован: 12.04.2008 18:32:38

Re: Препроцессор синтаксиса для FPC

Сообщение vada » 17.09.2013 15:31:31

в C есть всякие другие неприятности и нехорошие вещи

Нет гармонии во вселенной.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Препроцессор синтаксиса для FPC

Сообщение carrots » 18.09.2013 19:14:30

vada писал(а):Не понимаю, зачем писать на паскале? Пишите на С. Там препроцессор со своими попугаями прямо из коробки.
Нравится паскалевский синтаксис, можно своий хидер сделать с нужными словами и вперед. Уже где-то терли эту тему.


Я и пишу на C, C++, C# и других подобных языках, но сейчас мне нужен быстрый, кроссплатформенный компилятор, генерирующий быстрый код с поддержкой пропертей поддерживающих индексы и чтоб все это записывалось в rtti, нужна такая штука как for in или foreach, нужно еще много вещей которые в c++ достигаются до невозможности сложно.. .

Так например должен выглядеть скрипт который из youtube будет брать плейлист, парсить его и по своему выводить на сайте, при чем один и тот-же модуль обработки должен использоваться в скриптовом движке и компилируемом, а доступ к параметрам xml процедурным:
Код: Выделить всё
for item in xml(httpget(playListURL)).findByTag('entry') do
   uout += '<a onClick="player.src = '''+item['content']['src']+'''">' + item['title']
               + '<br /><img src="'+item['media:group']['media:thumbnail']['url']+'">'
               + '</a>'+item['published'];

На FPC это реализуется элементарно, но просветите меня как этого достичь в c++... К тому-же, тех самых питоновских приемов и лямбда функций нет и в нем..
Аватара пользователя
carrots
постоялец
 
Сообщения: 138
Зарегистрирован: 28.03.2008 02:13:02

Re: Препроцессор синтаксиса для FPC

Сообщение Logo » 20.09.2013 19:28:05

carrots писал(а):Logo, бывают такие случаи когда объявлять переменные сверху лучше, но в большинстве случаев это приводит к неудобству и даже к ошибкам, так как какой-то другой программер может захотеть воспользоваться данной переменной, чтоб не дописывать кашу сверху, в то время как она еще нужна. И... мы не портим синтаксис паскаля, просто добавляем некоторые возможности.
.......
.......
а подсветку синтаксиса можно поправить...

Локальные переменные никто не отменял, а глобальные там и должны быть, - сверху, дабы каждому видно было.
Подсветку, наверное, можно сделать, допилив плагины для СынЭдитора.

Штука это интересная и, наверное, каждый ее будет видеть по -своему. Мне бы, вот, SQL запросы писать прямо в теле программы хотолось бы, но портить синтаксис самого Паскаля, нет желания.
Logo
постоялец
 
Сообщения: 464
Зарегистрирован: 20.08.2008 01:00:47

Re: Препроцессор синтаксиса для FPC

Сообщение Vapaamies » 20.09.2013 21:57:57

Logo писал(а):Мне бы, вот, SQL запросы писать прямо в теле программы хотолось бы, но портить синтаксис самого Паскаля, нет желания.

Вы не поверите, но в Oracle есть (были?) Pro*C, Pro*COBOL и Pro*FORTRAN, -- препроцессоры, позволяющие писать запросы прямо в тексте программы. Pro*Pascal, правда, нету.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 272
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Препроцессор синтаксиса для FPC

Сообщение carrots » 21.09.2013 04:11:14

Vapaamies, Logo по идее такая технология уже есть встроенная в других языках, особенно рассчитанных на .NET, типа C#, Basic, называется LINQ, видел что она реализована на DWS.
В принципе штука хорошая особенно если она еще какие-то проверки на ошибки делает, можно ее интегрировать сюда-же, но в данный момент мне это не нужно, так как используется своя, локальная база написана на fpc и запросы делаются им-же самим с помощью дополнительных операторов или обрабатываются вручную.
+ по идее что-то подобное уже можно реализовать на том препроцессоре который есть, просто создать операторы привязанные к функциям формирующим соответствующие запросы для нужной базы.., получить совместимость с разными базами близкую к LINQ
Аватара пользователя
carrots
постоялец
 
Сообщения: 138
Зарегистрирован: 28.03.2008 02:13:02

Re: Препроцессор синтаксиса для FPC

Сообщение carrots » 23.09.2013 04:25:49

Там еще реализован предварительный вариант лямбда методов.
Мне не нравится как они реализованы в делфи, много места занимают, и не очень нравится как в С#, пока они реализованы в виде ссылки на выражение, аргументы передаются в виде массива вариантов который по умолчанию null, то есть можно не указывать:
Код: Выделить всё
proc := @(result := a[1]+a[2]/a[3]);
bb += proc([4,6,3]);
TimeSin := @(sin(now*10)*100);
ts := gg+TimeSin/2;
addJob(100,@(writeln(now)));

Если-бы узнать какие аргументы нужны в указываемом методе - можно было-бы автоматически воздавать функцию с нужными параметрами, в зависимости от того где наша лямбда функция будет использоваться.

+ еще там есть возможность вместо begin end ставить (), это может пригодиться для кротких выражений типа
Код: Выделить всё
while i < 100 do (next; b := sin(i));
, может быть удобно в тех-же лямбда функциях..

в перспективе хотелось бы сделать автоматическое подключение модулей с++, чтоб при вставке сишных модулей, они автоматически компилировались с помощью gcc, создавался хидер по подключаемому файлу и подключался полученный .o файл.
Аватара пользователя
carrots
постоялец
 
Сообщения: 138
Зарегистрирован: 28.03.2008 02:13:02


Вернуться в Разработки на нашем сайте

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru