#1 02-09-2010 06:48

Alien
Registered: 12-10-2008
Posts: 564

cleo script compiler

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

Для затравки пара скриптов, примерно описывающих синтаксис.
Скрипт 1
Нормальная арифметика выражений и всякое такое:cool:

/* Объявление статической скриптовой функции в теле скрипта */
[Opcode=0x0ACE]
static void DISPLAY_HELP_MESSAGE_FORMATTING(auto format, ...);

void digits_out(int digit1, int digit2, int digit3, int digit4)
{
	DISPLAY_HELP_MESSAGE_FORMATTING("%1d%1d%1d%1d", digit1, digit2, digit3, digit4);
}

// точка входа
void main()
{
	int stringRepresentation;
	int i;
	int intRepresentation[4];
	
	stringRepresentation = '1234';	// 0x31323334 
		
	for (i = 0; i < 4; i += 1)
	{
		intRepresentation[i] = (stringRepresentation >> (8 * i) & 0xFF) - '0';
	}
	
	// на экран будет выведено "4321"
	digits_out(intRepresentation[0], intRepresentation[1], intRepresentation[2], intRepresentation[3]);	
}

Думаю, дополнительных пояснений не требуется.
Во что код компилируется:

// This file was decompiled using sascm.ini published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 13.10.2007

{$VERSION 3.1.0027}
{$CLEO .cs}

//-------------MAIN---------------
0AB1: call_scm_func @Noname_46 0 
0A93: end_custom_thread 

:Noname_12
0ACE: show_formatted_text_box "%1d%1d%1d%1d" 0@ 1@ 2@ 3@  
0AB2: ret 0 

:Noname_46
0@ = 825373492 
1@ = 0 

:Noname_63
   not 1@ >= 4 
jf @Noname_142 
0A90: 6@ = 8 * 1@ // int 
0B15: 7@ = 0@ SHR 6@ 
0B10: 7@ = 7@ AND 255 
7@ -= 48 
0006: 2@(1@,4i) = 7@  // Note: the incorrect math opcode was used here
1@ += 1 
jump @Noname_63 

:Noname_142
0AB1: call_scm_func @Noname_12 4 2@ 3@ 4@ 5@ 
0AB2: ret 0

Скрипт 2
Использование array's index overflow для создания расширенного набора локальных переменных. Идея взята отсюда: http://sannybuilder.com/forums/viewtopic.php?id=995

#define ARRAY_SIZE 10

[Opcode=0x0AD3]
static void SPRINTF(auto destination, auto format, ...);
[Opcode=0x0ACA]
static void DISPLAY_HELP_MESSAGE(auto text);

void main()
{
	int address;
	/* на практике память выделяется по адресам памяти, кратным 4, на правильнее писать ARRAY_SIZE + 2 */
	if (ALLOCATE_MEMORY((ARRAY_SIZE + 2) * sizeof(int), out address))	
	{
		int base, i;
		int extra_ints[1];
		string test;
		base = (address - &extra_ints[0]) / sizeof(int);
		test = "";
		
		// использование выделенной памяти через array overflow
		for (i = 0; i < ARRAY_SIZE; i += 1)
		{
			extra_ints[base + i] = i;
		}
		
		for (i = 0; i < ARRAY_SIZE; i += 1)
		{
			SPRINTF(test, "%s%1d", test, extra_ints[base + i]);	
		}
		// будет выведено: 0123456789
		DISPLAY_HELP_MESSAGE(test);
		
		FREE_MEMORY(address);
	}
}

Во что компилируется:

// This file was decompiled using sascm.ini published by Seemann (http://sannybuilder.com/files/SASCM.rar) on 13.10.2007

{$VERSION 3.1.0027}
{$CLEO .cs}

//-------------MAIN---------------
0AB1: call_scm_func @Noname_12 0 
0A93: end_custom_thread 

:Noname_12
0AC8: 0@ = allocate_memory_size 48 
jf @Noname_204 
0AC7: 8@ = var 3@ offset 
0A8F: 9@ = 0@ - 8@ // int 
9@ /= 4 
0006: 1@ = 9@  // Note: the incorrect math opcode was used here
06D2: 4@v = "" // @v = string 
2@ = 0 

:Noname_74
   not 2@ >= 10 
jf @Noname_125 
0A8E: 8@ = 1@ + 2@ // int 
0006: 3@(8@,1i) = 2@  // Note: the incorrect math opcode was used here
2@ += 1 
jump @Noname_74 

:Noname_125
2@ = 0 

:Noname_132
   not 2@ >= 10 
jf @Noname_194 
0A8E: 8@ = 1@ + 2@ // int 
0AD3: sprintf 4@v "%s%1d" 4@v 3@(8@,1i) 
2@ += 1 
jump @Noname_132 

:Noname_194
0ACA: show_text_box 4@v 
0AC9: free_allocated_memory 0@ 

:Noname_204
0AB2: ret 0

А теперь о помощи. В GTA 4 мы имеем реальные имена скриптовых функций. Их надо соотнести с тем, что мы имеем в III modding'е (то, что принято называть опкодами).
Поэтому, если кто-то хочет заняться составлением этого списка, то в прикреплении находится небольшая тулза (будет хотеть .NET Framework 3.5) и 2 начатые базы BASIC_OPCODES.xml и CLEO_OPCODES.xml. Их можно использовать для примера. Описывать абсолютно все опкоды не имеет смысла - только наиболее часто используемые. Не нужны опкоды для работы с метками, не нужны опкоды для арифметики чисел...
Например, опкод 0001: wait 0 явно соотносится с функцией void WAIT(int time_in_ms). Тут все просто. Но есть несколько моментов, о которых следует упомянуть.
Первый момент - есть функции, возвращающие значения:

int CREATE_CHAR(int pedType, int mi, float x, float y, float z)

Возвращаемое значение - это всегда последний операнд в опкоде:

009A=6,%6d% = create_actor_pedtype %1d% model %2o% at %3d% %4d% %5d%

Второй момент - есть функции, возвращающие несколько значений, в этом случае они описываются в списке параметров с аттрибутом 'out':

void GET_CHAR_COORDINATES(int handle, out float x, out float y, out float z)

Третий момент - в CLEO есть так называемые IF and SET опкоды, которые устанавливают значение логической операции TRUE или FALSE. Такие функции нужно описывать так:

bool ALLOCATE_MEMORY(int size, out int pointer)

Четвертый момент - в CLEO многие опкоды не типизированы. Например, в качестве параметра могут приниматься либо scm-строки, либо указатели на C-строки. Для таких случаев введен тип auto. Для параметров такого типа компилятор не будет выполнять проверку и приведение типов.

int OPEN_FILE(auto path, auto mode)

Offline

#2 02-09-2010 10:13

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: cleo script compiler

ИМХО лучше подучить несложный язык скриптинга, чем работать через интерпритатор с неизвестным КПД о_О


GIMS developer

Offline

#3 02-09-2010 12:24

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: cleo script compiler

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

А вообще я бы начал с другой стороны. Написать сначала не обертку для низкоуровневого синтаксиса, а compile-on-fly прогу. Т.е. программу (или модуль в составе CLEO), которая бы читала текстовые исходники (с обычными опкодами), компилировала их в язык scm и запускала на исполнение. Аналог LUA. Т.е. при внесении изменений в исходник не требовалась бы запускать SB и перекомпилировать скрипт.

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

Offline

#4 02-09-2010 18:48

Alien
Registered: 12-10-2008
Posts: 564

Re: cleo script compiler

3Doomer wrote:

ИМХО лучше подучить несложный язык скриптинга, чем работать через интерпритатор с неизвестным КПД о_О

Что такое КПД? Скорость исполнения? или скорость компиляции? или еще что-то?
@Seemann -
C-подобный синтаксис выбран не из соображений понятности для новичков, а из соображений удобства реализации парсера и естественной соотносимости с низким уровнем. Вообще говоря, язык будет рассчитан явно не на новичков, а на опытных программистов или программеров-любителей, знакомых с языками типа C. Для них освоение такого скриптового языка - дело пары часов.
По поводу JIT-компиляции - предложение интересное, а главное, вполне реализуемое. Но это не то, чем я сейчас занимаюсь, так что вопрос отложим хотя бы до тех пор, пока не будет полностью рабочий и опробованный обычный компилятор.

Т.е. при внесении изменений в исходник не требовалась бы запускать SB и перекомпилировать скрипт.

Уточнюсь. cleo script compiler - это не компилятор из C-подобного языка в язык SB. Вообще, параллельно с компилятором идет выпиливание простенькой IDE к нему. Получится продукт, независимый от Sanny Builder'а (Хотя Sanny Builder будет удобно использовать в качестве декомпилятора и просмотра кода на низком уровне).
Ну а так, почему я решил этим заняться - просто проба сил. А почему компилятор для CLEO скриптов - да просто мне до жути надоело иметь дело с листингами скриптов на низком уровне.

______________________________________
А теперь кратко о языке.
[large]Типы данных[/large]
Имеются следующие типы данных:
int - 4-байтовое целое
float - вещественное одинарной точности
gxt - строка из 7 или менее символов
string - строка из 15 или менее символов (есть возможность использовать constant string длиной до 127 символов)
bool - логическое. Нельзя объявлять переменные этого типа - значения этого типа могут только возвращаться статическими функциями (опкодами) или пользовательскими функциями. Существуют 2 константных значения - true и false.
void - тип для функций, не возвращающих значения.
А также массивы: int[], float[], gxt[], string[].
[large]Объявление данных[/large]
Данные можно объявлять в теле функции в любом месте. Все, что объявлено между { и } действует только внутри этого блока и перегружает все одноименные символы из родительских блоков.
Объявление данных в глобальной области видимости в CLEO скриптах запрещено. Зато можно описать некоторые внешние символы из майна следующим образом:

[FixedVarPosition=2]
extern int Player;
[FixedVarPosition=3]
extern int PlayerChar;

Естественно, все, что объявляется должно умещаться в набор 32 локальных переменных (в случае с миссиями - 1022) и при этом должно оставаться место для генерации компилятором временных переменных. Для обращения к таймерам 32@, 33@ используются предопределенные идентификаторы timer1, timer2.
[large]Операторы в математических инструкциях[/large]
Используются следующие операторы:

= (присваивание)
+, += (сложение), 
-, -= (вычитание), 
*, -= (умножение), 
/, /= (деление), 
&, &=(поразрядное и), 
|, |= (поразрядное или), 
^, ^= (поразрядное исключающее или)
<<, >>, <<=, >>= (логические сдвиги)
- (минус, унарный)
sizeof (получение размера переменной / типа в байтах)
~ (поразрядное отрицание. унарный)
%, %= (модуло)
&& (логическое и)
|| (логическое или)
& (взятие ссылки на переменную, унарный)
(int) (приведение float к int)
(float) (приведение int к float)
() (вызов функции или группировка операторов по первичности)
== (тождественное равенство)
>, <, >=, <=, != (операторы сравнения)
! (логическое отрицание, унарный)

Операторов постфиксного и префиксного инкремента/декремента нет и не будет. Оператора ?: также нет. Насчет других операторов - они имеют тот же приоритет и ассоциативность, что и в языке C.
Типы float <-> int приводятся автоматически, но лучше указывать приведение типов явно, чтобы не возникало неожиданных казусов.
Например, выражение 3 / 4 == 0, а выражение (float)3 / 4 == 0.75.
[large]Высокоуровневые конструкции[/large]
Используются следующие конструкции (кажется, все те же самые, что и в C): if, if-else, for, while, do-while, switch.
По поводу switch, здесь используется подход C# - неявный fall-through запрещен. Каждая ветвь исполнения должна оканчиваться либо на break, либо на goto case/ goto default.

ЗЫ: кто заинтересовался, спрашивайте, что непонятно и нужно пояснить.

Last edited by Alien (02-09-2010 19:40)

Offline

#5 02-09-2010 20:23

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: cleo script compiler

под КПД я подразумевал надёжность и оптимизацию получаемого кода...я бы предпочёл вручную контроллировать)


GIMS developer

Offline

#6 03-09-2010 12:52

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: cleo script compiler

Я вообще не понял зачем такое нужно. Ну раз не хочется писать скрипт на низкоуровневом виде, то можно свою ASI библиотеку подключить. Можно подробней объяснить в чём суть представленного выше?

Offline

#7 04-09-2010 07:08

Alien
Registered: 12-10-2008
Posts: 564

Re: cleo script compiler

@Sw[ee]t - А разве ASI и CLEO скрипт - это одно и то же? Для того, чтобы написать делающую что-то полезное ASI библиотеку, нужно еще потанцевать с бубном вокруг грязных хаков. Посмотреть хотя бы на тот же gta_dll. Там половина всего кода - это объявления такого рода:

void (__thiscall *CPed__GiveWeapon)(CPed *, int weapon, int ammo) = 
(void (__thiscall *)(CPed *, int, int))(0x5E6080);

Это было во-первых. Во-вторых, нужно еще воткнуть эту ASI куда-то в процесс исполнения игры. Туда, куда воткнулась одна ASI, вторую уже не воткнешь, поэтому ASI библиотек, так мало, а CLEO скриптов так много.
А смысл перехода на этот язык - в общем повышении читабельности кода, в повышении защищенности.
Сколько здесь на форуме вопросов типа:
"Почему, какие бы координаты я ни поставил, я всегда появляюсь в центре карты?"

00A1: put_actor $PLAYER_ACTOR at 345 306 998

А все потому, что нет типизации. Да и от самого подхода к командам: опкод, операнды... - нужно отойти. За каждой командой нужно лезть в Opcode Search Tool, а за некоторыми вообще в SASCM.ini.
С именами гораздо удобнее: нажал ctrl+space - вывалился список всех команд, набрал первые буквы - получил свою команду.
d4abada47b80t.jpg
@3Doomer -
По надежности высокоуровневый код будет всегда выигрывать у низкоуровневого. Ну а по оптимизации - ты получаешь только тот код, который пишешь. Каждая инструкция компилируется сама в себя. Есть ли разница, пишешь ты на низком уровне:

if
0AB0: 0x41// A
then
// ...
end

или на высоком:

if (IS_KEY_PRESSED('A'))
{
// ...
}

(Здесь ты кстати только сэкономишь на одной инструкции - 00D6: if 0).

ЗЫ: Забыл сказать, что комплексные условия, которые раньше образовывались с 00D6, теперь будут образовываться при помощи соответствующих переходов. То есть можно будет писать следующим образом:

if (PLAYER_DEFINED(0) && CHAR_HAS_WEAPON(PlayerChar, 28))
...

Если первое подусловие ложно, то второе проверяеться не будет и вылета не последует.

Offline

#8 04-09-2010 07:41

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: cleo script compiler

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

asi и cleo, на сколько я понимаюд, различаются. asi - dllка, выдаёт команды непосредственно exe игры, а скрипты - скриптовому движку


GIMS developer

Offline

#9 04-09-2010 08:33

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: cleo script compiler

Меня смутило слово CLEO в названии. Теперь суть проекта ясна. Это скорее альтернатива саннику, или развитие идей Point Compiler. Что ж удачи. Хотя у меня есть определенные сомнения в будущей популярности си-подобного синтаксиса среди скриптеров.

Offline

#10 04-09-2010 09:14

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: cleo script compiler

@Alien - я всё понял. Довольно интересно сделать что-то типа natives гта4 smile
Присоединяюсь к симэну и желаю удачи!

Offline

#11 05-09-2010 09:41

Alien
Registered: 12-10-2008
Posts: 564

Re: cleo script compiler

За пожелания удачи всем спасибо. Насколько я понял, желающих помочь в составлении списка статических функций пока не нашлось? Ну чтож, буду справляться своими силами.
Кстати, если тут есть IV скриптеры, чем отличаются функции MESSAGE от NM_MESSAGE и можно ли их соотнести с show_text_highpriority и show_text_lowpriority?

3Doomer wrote:

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

Это зависит и от асма. Если он содержит complex instruction set, то это представляет определенный простор для оптимизации. Взять тот же x86. Умножение регистра eax на 40 в общем случае выглядит так:

imul eax, 40

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

lea eax, [eax + 4*eax]
shl eax, 3

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

extra_ints[base + i] = i / extra_ints[base + i];

Чтобы дважды не вычислялось base + i, его можно вынести в отдельное выражение:

int index = base + i;
extra_ints[index] = i / extra_ints[index];
Seemann wrote:

Хотя у меня есть определенные сомнения в будущей популярности си-подобного синтаксиса среди скриптеров.

Да уж. Не понимаю что такого страшного в сишном синтаксисе? Все равно среднестатистический гта-скриптер (как правило школьник 8-9 классов) будет с увлечением читать о таблицах переходов и о том, куда надо поставить нолик, а куда единичку, но будет страшно бояться разобраться в структуре switch-блока.:D

Last edited by Alien (05-09-2010 09:47)

Offline

#12 05-09-2010 10:22

3Doomer
From: КаZан
Registered: 14-05-2008
Posts: 659
Website

Re: cleo script compiler

в общем, этот проект готовит школьничков к серьёзному языку программирования))
всё о России думаешь:lol::D

Last edited by 3Doomer (05-09-2010 10:23)


GIMS developer

Offline

#13 05-09-2010 15:10

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: cleo script compiler

"О себе бы подумал, ты ведь не отдыхаешь совсем. Всё о Роисси думаешь!"

Offline

#14 27-09-2010 07:33

Alien
Registered: 12-10-2008
Posts: 564

Re: cleo script compiler

Возник вопрос. Нужна ли поддержка меток и переходов (goto)? В некоторых случаях эта конструкция языка может помочь сделать код более эффективным, но при этом нарушается структурированность программы. Учитывая необъяснимую тягу скриптеров к меткам и переходам в SB, есть предложение выкинуть ее нафик, ибо за всю свою жизнь мне ни разу не пришлось ей воспользоваться (SB и asm не в счет), а вот неопытных скриптеров оградить от этого зла надо.
И еще. Каким образом подходить к скриптовым константам (педтипам, номерам клавиш, номерам ооружия и проч.)? Тут 2 варианта - либо нативная поддержка (как с опкодами), либо определение во внешних подключаемых модулях (include)? Этакая стандартная библиотека...

Offline

#15 27-09-2010 09:35

Sw[ee]t
From: Нижний Новгород
Registered: 16-02-2009
Posts: 686
Website

Re: cleo script compiler

И еще. Каким образом подходить к скриптовым константам (педтипам, номерам клавиш, номерам ооружия и проч.)? Тут 2 варианта - либо нативная поддержка (как с опкодами), либо определение во внешних подключаемых модулях (include)? Этакая стандартная библиотека...

Я за вариант 2 (инклюды). Их исправить можно, если что не нравится.

Offline

#16 27-09-2010 13:49

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: cleo script compiler

Учитывая необъяснимую тягу скриптеров к меткам и переходам в SB, есть предложение выкинуть ее нафик

Хоть все и пользуются, все равно надо убрать... Где логика?

Все зависит от возможностей языка. Если язык позволяет обходиться без меток, поддержка их не нужна. Если нет - нужна. Все просто.

Offline

#17 27-09-2010 18:15

listener
From: Vice City
Registered: 09-11-2006
Posts: 616
Website

Re: cleo script compiler

@Alien - Метки/goto - однозначно нет.
Константы - определять через const.

Для встроенных типов, я предпологаю в C4 ввести слово immutable, например:
immutable PEDHANDLE;
immutable VEHHANDLE;
А потом использовать PEDHANDLE в качестве типа.
полноценный typedef, скорее всего, не нужен.

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

Offline

#18 28-09-2010 21:17

Alien
Registered: 12-10-2008
Posts: 564

Re: cleo script compiler

ОК, от goto отказываемся раз и навсегда.=)
@listener - Ага, защищенные скриптовые хэндлы - это полезно. Только у меня они скорее будут как самостоятельные типы, явно приводимые к int при необходимости (через оператор (int)), а неявно не приводимые. Сделать эти типы объявляемыми в коде (через typedef/immutable) не выйдет, потому что хэндлы используются в основном скриптовыми функциями, хранимыми в автономных постоянных хранилищах - базах данных (чтобы не пришлось парсить много кода при каждой компиляции - они будут грузиться 1 раз в момент запуска IDE). Как их потом привязывать к этим объявлениям в коде?

Offline

Board footer

Powered by FluxBB