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

Установка

ZINC является альтернативным синтаксисом VJASS и соответственно повторяет его баги и способ установки.

zinc

Из-за синтаксиса несовместимого с VJASS все блоки должны быть обёрнуты в специальную директиву:
//! zinc
// Этот блок будет интерпретирован как ZINC
//! endzinc

import

Немного отличается от VJASS аналога тем, что позволяет явно указать как интерпретировать импортируемый файл:
//! zinc
	// Будет интерпретирован как бог на душу положит
	//! import "A.j"

	// Будет интерпретирован как VJASS
	//! import vjass "B.j"

	// Будет интерпретирован как ZINC
	//! import zinc "C.j"
//! endzinc
Наилучшим способом будет организовать структуру таким образом:
D:/MyMaps/MyAwesomeMap
	└── map.w3x
		├── main.zn
		└── src
			├── lib
			|	├── libA.zn
			|	└── libB.zn
			└── spell
				├── spellA.zn
				└── spellB.zn
Нестандартный код карты
//! zinc
	//! import "main.zn"
//! endzinc
main.j
//! import "spell/spellA.zn"
//! import "spell/spellB.zn"
spellA.j
//! import "../lib/libA.zn"
spellB.j
//! import "../lib/libB.zn"
Теперь при сохранении карты в редакторе код будет собран из указанных файлов, которые можно просто редактировать и хранить на гитхабе.

Операторы

Приоритет Ассоциативность Оператор Описание Пример
1 Левая () Оператор скобки (a+b)*c
2 Левая [] Доступ к индексу a[b]
2 Левая () Вызов функции a(b)
3 Правая ! Логическое НЕ !a
3 Правая - Математическая смена знака -a
4 Левая * Умножение a*b
4 Левая / Деление a/b
5 Левая + Сложение a+b
5 Левая - Вычитание a-b
6 Левая Меньше a<b
6 Левая > Больше a>b
6 Левая <= Меньше или равно a<=b
6 Левая >= Больше или равно a>=b
7 Левая == Равно a==b
7 Левая != Не равно a!=b
8 Левая && Логическое И a&&b
9 Левая || Логическое ИЛИ a||b
10 Правая = Присваивание a=b
10 Правая *= Присваивающее умножение a*=b
10 Правая /= Присваивающее деление a/=b
10 Правая += Присваивающее сложение a+=b
10 Правая -= Присваивающее вычитание a-=b
11 Левая , Перечисление a,b

library

Библиотеки основная структурная единица языка. Код вне библиотек недопустим.
library MyLib {
// Содержимое библиотеки
}

requires

Служит для явного указания зависимости одной библиотеки от другой:
library A requires B, C {}

library B {}

library C {}
При компиляции код библиотек, указанных в requires будет помещён выше исходной библиотеки.

Минутка рукожопости

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

optional

Указывает компилятору, что отсутствие определённой библиотеки это штатная ситуация и если при компиляции библиотека не будет найдена, то ошибка не будет сгенерирована.
library A requires B, optional C {}

library B {}

onInit

Специально обученная функция, которая будет вызвана перед завершением функции main в war3map.j.
library A {
	function onInit(){
		// Этот блок будет вызван перед завершением функции main
	}
}

Функции

Функции должны быть объявлены в корне библиотеки. В дальнейшем описании функций библиотека будет опущена для краткости.
library A {
	function myFunc(){
		// Код функции
	}
}

Аргументы

Указываются внутри скобок:
function A(integer a, real b) {
	// Код функции
}

Возврат значения

Для указания типа возвращаемого значения служит специально обученная стрелка:
function A(integer a, integer b) -> integer {
	return a + b;
}

Вызов функции

function A(integer a, integer b) -> integer {
	return a + b;
}

function B(){
	A(1, A(2, 3));
}

Анонимные функции

Они же лямбды - очень удобная вещь, которая позволяет лишний раз не выдумывать шикарные имена передаваемым функциям:
function A(){
	TimerStart(CreateTimer(), 1., false, function(){
		// Этот код исполнится по истечению таймера
	});
}
В JASS это скомпилится примерно таким образом:
function A_1 takes nothing returns nothing
	// Этот код исполнится по истечению таймера
endfunction

function A takes nothing returns nothing
	call TimerStart(CreateTimer(), 1., false, function A_1)
endfunction

Переменные

Для различия между глобальными и локальными переменными не определено дополнительного синтаксиса. Всё зависит от места, в котором они объявлены.

Глобальные переменные

Объявляются только в корне библиотеки:
library A {
	integer B;
	integer C = 2;
}

constant

Для запрета изменения значения в процессе исполнения код используется ключевое слово constant.
library A {
	constant integer B = 1;
	constant integer C = 2;
}
Переменные, объявленые как constant обязательно должны быть инициализированы при объявлении.

Локальные переменные

Объявляются только в функции до первого действия:
library A {
	function B() {
		integer C;
		integer D = 2;
	}
}

Короткая запись

Любые переменные одного типа могут быть объявлены одним выражением:
library A {
	integer B, C = 1, D = 2;
	
	function onInit(){
		integer E, F = 3;
	} 
}

Массивы

Для объявления массива используются квадратные скобки:
library A {
	integer B[], C = 1, D = 2;
	
	function onInit(){
		integer E[], F = 3;
	} 
}

Присваивание

library A {
	integer B, C[];
	
	function onInit(){
		integer D[], E;
		
		B = 1;
		C[0] = 2;
		D[0] = 3;
		E = 4;
	} 
}

Модификаторы доступа

Определяют доступность содержимого библиотеки из других библиотек. По умолчанию все переменные и функции внутри библиотеки, тобишь невозможно вызвать функцию или получить значение переменной одной библиотеки из другой. Чтоб изменить это поведение используется ключевое слово public:
library A {
	public integer C = 1;
	public function D(){}
	public {
		integer E = 2;
		function F(){};
	}
}

library B() {
	function onInit(){
		C = 3;
		D();
		E = 3;
		F();
	}
}

Условия

Настоятельно рекомендую прочитать эту статью, здесь же приведу различия между синтаксисом:

ZINC

if (A) {
	// этот блок выполнится, если A истинно
}

JASS

if A then
	// этот блок выполнится, если A истинно
endif

ZINC

if (A) {
	// этот блок выполнится если A истинно
} else {
	// этот блок выполнится если A ложно
}

JASS

if A then
	// этот блок выполнится если A истинно
else
	// этот блок выполнится если A ложно
endif

ZINC

if (A) {
	// этот блок выполнится если A истинно
} else if (B) {
	// этот блок выполнится если A ложно и B истинно
} else if (C) {
	// этот блок выполнится если A ложно, B ложно и C истинно
} else {
	// этот блок выполнится если A ложно, B ложно и C ложно
}

JASS

if A then
	// этот блок выполнится если A истинно
elseif B then
	// этот блок выполнится если A ложно и B истинно
elseif C then
	// этот блок выполнится если A ложно, B ложно и C истинно
else
	// этот блок выполнится если A ложно, B ложно и C ложно
endif
Если условие содержит одно выражение, то скобки можно опустить. На этой особенности построен elseif, а так же удобно использовать в функциях подобного рода:
function MaxI(integer a, integer b) -> integer {
	if (a > b) return a;
	return b;
}

Циклы

Все циклы при компиляции будут превращены в loop.

while

ZINC

while(A){
	// Этот блок будет исполняться пока A истинно
}

JASS

loop
	exitwhen not A
	// Этот блок будет исполняться пока A истинно
endloop

for

ZINC

i = 5;
for (0 < i <= 10){
	// Этот блок будет выполняться пока i > 0 и i <= 10
	// ...
	// В конце итерации цикла произойдёт неявный инкримент i
}

JASS

set i = 5
loop
	exitwhen i <= 0 or i > 10 // Этот блок будет выполняться пока i > 0 и i <= 10
	// ...
	set i = i + 1 // В конце итерации цикла произойдёт неявный инкримент i
endloop

ZINC

i = 5;
for (10 >= i > 0){
	// Этот блок будет выполняться пока i > 0 и i <= 10
	// ...
	// В конце итерации цикла произойдёт неявный декримент i
}

JASS

set i = 5
loop
	exitwhen i <= 0 or i > 10 // Этот блок будет выполняться пока i > 0 и i <= 10
	// ...
	set i = i - 1 // В конце итерации цикла произойдёт неявный декримент i
endloop

Минутка рукожопости

Для цикла for можно использовать только переменную. Хотя синтаксис позволяет использовать элемент массива.

break

Используется для остановки цикла:

ZINC

while(true){
	if (!A) break; // Прерываем цикл если A ложно
}

JASS

loop
	exitwhen not true
	if not A then
		exitwhen true // Прерываем цикл если A ложно
	endif
endloop

Полезные ссылки

`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.