Добавлен , опубликован

Что это?

cJass - это еще одно расширение языка JASS, которое полностью совместимо с популярным vJass. Цель его создания - дать программистам еще больше возможностей по созданию простого и качественного кода. Основными направлениями являются:
  1. Макросредства и стандартная библиотека - избавляют от рутины, позволяя сконцентрироваться на основном коде.
  2. Упрощение синтаксиса - мы не хотим снова начинать спор, какой синтаксис лучше (блоки через begin & end или {}), и более того, мы не навязываем свою точку зрения - все конструкции cJass имеют JASS-style аналоги, тем не менее мы предоставляем выбор.
  3. Оптимизация карты - основная концепция cJass - это то, что все языковые конструкции не должны сказываться на качестве генерируемого кода. Также мы работаем над встроенным оптимизатором.

Как это использовать?

Просто скачайте дистрибутив (пароль для архива: cjass), распакуйте и запустите инсталлятор. У вас уже должен быть установлен Jass New Gen Pack.
Ознакомиться с возможностями можно, прочитав руководство пользователя cJass (off-line версия этого файла также имеется в директории программы).

Что-то не работает!

В настоящий момент мы активно дополняем язык всевозможными конструкциями, поэтому полноценная проверка синтаксиса пока отсутствует. Но мы всегда внимательно изучаем
bug-репорты, которые можно оставить в этой теме.

У меня есть идея: а не плохо бы...

Мы всегда рады выслушать Ваши идеи и предложения по внесению каких либо новых возможностей в язык, расширению стандартной библиотеки и т.д. Иногда мы даже действительно делаем то, что Вы нам предлагаете ;) Наша секция обратной связи ждет Вас!
И напоследок немного истории.
А история программы начинается на ресурсе wc3c.net, когда Vexorian, выслушав предложение от ADOLF'a сделать инструкции инкремента и декремента создает ветку с обсуждением синтаксиса... и благополучно забывает об этом. Тогда ADOLF подумал: "А неплохо было бы сделать свой парсер и включить в него всяких вкусностей". Изначально программа весила меньше заветных 9000 байт, распространялась по сети ICQ/Jabber и ее использовали несколько человек.
Однажды один из ее пользователей - Van Damm (впоследствии стал соавтором) сказал "это очень удобно!" (это было сказано про то, что можно вызывать функции без ключевого слова call) - и тогда мы решили, что если это удобно, почему бы не выложить программу на публичное обозрение. Благодаря zibade у нас появился сайт, где сразу стал отписываться Dark Dragon, который помог выявить львиную долю багов и внес множество интересных предложений.
С тех пор прошло много времени, мы сделали много новых версий, вес программы вырос в 3 раза (сейчас 26 Кбайт). На данный момент у нас есть планы, касающиеся многих конструкций, оптимизатора, и всего прочего.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
18
14 лет назад
0
[b]ADOLF[/b], наконецто анонимки! Скорее бы.
0
33
14 лет назад
0
уже) только не anonym, а lambda
0
18
14 лет назад
0
bb:Я уже заметил -_-. АдикХелпер очень не дружит со статик ифами векса, таймер утилс пришлось сильно отредактировать. Будешь что-нибудь делать с этими ифами?
0
33
14 лет назад
0
ну я вроде пытался их сдружить - либо как вариант юзать #if из сЖасс
а вообще код бы неповредил, где оно баги выдает
0
18
14 лет назад
0
[cut=TimerUtils][code]library TimerUtils initializer init
*********************************************************************
* TimerUtils (red+blue+orange flavors for 1.24b+)
* ----------
*
* To implement it , create a custom text trigger called TimerUtils
* and paste the contents of this script there.
*
* To copy from a map to another, copy the trigger holding this
* library to your map.
*
* (requires vJass) More scripts: htt://www.wc3c.net
*
* For your timer needs:
* * Attaching
* * Recycling (with double-free protection)
*
* set t=NewTimer() : Get a timer (alternative to CreateTimer)
* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
* SetTimerData(t,2) : Attach value 2 to timer
* GetTimerData(t) : Get the timer's value.
* You can assume a timer's value is 0
* after NewTimer.
*
* Multi-flavor:
* Set USE_HASH_TABLE to true if you don't want to complicate your life.
*
* If you like speed and giberish try learning about the other flavors.
*
********************************************************************
================================================================
globals
How to tweak timer utils:
USE_HASH_TABLE = true (new blue)
* SAFEST
* SLOWEST (though hash tables are kind of fast)

USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange)
* kinda safe (except there is a limit in the number of timers)
* ALMOST FAST

USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
* THE FASTEST (though is only faster than the previous method
after using the optimizer on the map)
* THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
work)

private constant boolean USE_HASH_TABLE = true
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET

Timers to preload at map init:
private constant integer QUANTITY = 256

Changing this to something big will allow you to keep recycling
timers even when there are already AN INCREDIBLE AMOUNT of timers in
the stack. But it will make things far slower so that's probably a bad idea...
private constant integer ARRAY_SIZE = 8190
endglobals
==================================================================================================
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if(USE_HASH_TABLE) then
new blue
call SaveInteger(ht,0,GetHandleId(t), value)

elseif (USE_FLEXIBLE_OFFSET) then
orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
new blue
return LoadInteger(ht,0,GetHandleId(t) )

elseif (USE_FLEXIBLE_OFFSET) then
orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
use a totally random number here, the more improbable someone uses it, the better.
endglobals
==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
If this happens then the QUANTITY rule has already been broken, try to fix the
issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
set tT[0]=CreateTimer()
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==ARRAY_SIZE) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
local integer i=0
local integer o=-1
local boolean oops = false

static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop

if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
If this message doesn't appear then there is so much
handle id fragmentation that it was impossible to preload
so many timers and the thread crashed! Therefore this
debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary[/code][/cut]В SetTimerData на первом же elseif'е синтакс еррор в вексовском компиляторе.
[size=1][i]Nekit1234007 добавил:[/i][/size]
Разумеется, это неотредактированная версия.
0
33
14 лет назад
0
а без адика еррора нет? вечером гляну
0
18
14 лет назад
0
[quote=ADOLF]без адика еррора нет?[/quote]
Да, нет.
0
33
14 лет назад
0
хорошо, посмотрю)
0
18
14 лет назад
0
У векса лучше сделаны анонимки.
Два одинаковых примера, один на cJass, второй на зинке:
[cut=cJass][code]library A requires TimerUtils
{
#include "cj_types.j"
struct A
{
static thistype create()
{
thistype this=thistype.allocate()
timer t=NewTimer()
SetTimerData(t,this)
TimerStart(CreateTimer(),1.,false,lambda void()
{
thistype this=GetTimerData(GetExpiredTimer())
})
return this
}
}
}[/code][/cut]
[cut=Zinc][code]//! zinc
library B requires TimerUtils
{
struct A
{
static method create()->thistype
{
thistype this=thistype.allocate();
timer t=NewTimer();
SetTimerData(t,this);
TimerStart(CreateTimer(),1.,false,function()
{
thistype this=GetTimerData(GetExpiredTimer());
});
return this;
}
}
}
! endzinc[/code][/cut]
cJass'овый не работает, зинковый работает.
0
33
14 лет назад
0
Nekit1234007, нет, мой тоже пашет, если писать
                A this=GetTimerData(GetExpiredTimer())
так, я понял) дело в том, что зистип можно использовать только внутри метода, у меня же функция пишеться поверх струткуры (возмите да гляньте), а векс меняет имена методов, т.е. я не могу делать из анонимных функций статические методы
0
18
14 лет назад
0
[b]ADOLF[/b], да я понимаю и глядел, но так как можно делать у векса удобнее, имхо.[quote=ADOLF]я не могу делать из анонимных функций статические методы[/quote]
Ну так смоги О_О.
0
33
14 лет назад
0
векс меняет их имена, я теоритически могу попробывать их поподгонять... хм... я могу сделать это даже не теоритически. я подумаю, спасибо за репорт. баги с ифами если что еще не смотрел
ADOLF добавил:
Ну так смоги О_О.
как все просто на словах)
0
18
14 лет назад
0
[off]<offtop>[/off] Я также понимаю, что на асме прогать - не плюшки кушать, но векс на паскале делает, а то что можно делать на паскале можно и на асме и даже больше и оптимизированнее. [off]</offtop> Этот оффтоп является безпруфным, и отражает мои знания, которые могут не совпадать с действительностью.[/off]
0
33
14 лет назад
0
дело не в сложности. дело в том, что мне надо предугадывать то, как именно будет переименован статический метод, учитывая что структуры могут быть приватными и т.д. (а я благополучно кладу на это т.е. вообще не обрабатываю библиотеки и т.д.) - как резальтат ради маленькой плюшки надо проделывать кучу работы
0
13
14 лет назад
0
Если анонимку ставить непосредственно перед использующей функцией, проблем с именами быть не должно.
было
library A requires TimerUtils
{
    #include "cj_types.j"

    struct A
    {
        static thistype create()
        {
            thistype this=thistype.allocate()
            timer t=NewTimer()
            SetTimerData(t,this)
            TimerStart(CreateTimer(),1.,false,lambda void()
            {
                thistype this=GetTimerData(GetExpiredTimer())
            })
            return this
        }
    }
}
стало
library A requires TimerUtils
{
struct A
{
nothing anon_func_name_here()
{
thistype this=GetTimerData(GetExpiredTimer())
}
static thistype create()
{
thistype this=thistype.allocate()
timer t=NewTimer()
SetTimerData(t,this)
TimerStart(CreateTimer(),1.,false,function anon_func_name_here)
return this
}
}
}
Только ведь Векс там ещё с переменными крутит.
И может мне кто-нибудь объяснить, на кой чорт эта лямбда? Неужели нельзя реагировать на имя типа со скобкой или хотя бы слово function?
0
18
14 лет назад
0
[b]Sebra[/b], моя проблема уже исправлена в 1.4.1.34. Тоесть мой способ уже работает :).
0
13
14 лет назад
0
Рад за тебя :)
Но вот новое ключевое слово портит всю малину. :(
0
18
14 лет назад
0
bb:Согласен. Если бы можно было не писать, или хотя бы сокрашать до &#955; :D
0
33
14 лет назад
0
без слова технически сложно ловить функции, учитывая си стайл обьвления. т.е. синтаксис и так сложный для понимания препроцессором
0
13
14 лет назад
0
То есть тип со скобками в аргументах функции отловить не удаётся?
И использовать вместо "lambda" слово "function" тоже?
Ведь Векс неспроста отказывается вводить ключевые слова.
Всегда есть шанс в чьей-то работе нарваться на переменную "lambda".
Возможно, достаточно отлавливать только "boolexpr()" и "nothing()".
0
33
14 лет назад
0
ну как бы я и так ввожу кучу кейвордов, т.е. в любом случае куда то та да попадем)
type()
ну это было бы заметно технически сложнее
0
13
14 лет назад
0
Может я чего пропустил, но пока были только define и include.
Не считая диезов, конечно.
А lambda имеет гораздо больше шансов встретиться как нормальное имя.
ForGroup(g,function nothing(){DoNothing();}) тоже сложнее lambda?
Хотелось бы взглянуть на применение анонимных функций кроме nothing() и boolean().
0
33
14 лет назад
0
Хотелось бы взглянуть на применение анонимных функций кроме nothing() и boolean()
хз, я просто не хочу вводить какие либо искувственные ограничения
ForGroup(g,function nothing(){DoNothing();}) тоже сложнее lambda?
да) в моем случае - да
ADOLF добавил:
вообще как по мне однослово ну ничего не портит, у векса тоже нужно писать фунцтион, так что...
0
13
14 лет назад
0
function в любом случае не идентификатор.
А как использовать переменные типа code кроме nothing() и boolean() я не знаю.
Да и судя по тому, что все молчат это невозможно.
Так что эти ограничения вполне естественные.
0
25
14 лет назад
0
Кстати было бы удобно добавить "getvartype" для оптимизации контейнеров, и т.п.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.