Регрессии и ошибки NXScript

Started by SKYnv, September 22, 2012, 07:03:27 PM

Previous topic - Next topic

SKYnv

Тема для репортов относительно NXScript, если кто заметил ошибки или странности не забывайте писать здесь.

1) пре инкремент
работает как декремент

2) uint32 conversion
не работает данная конвертация

3) парсер и "//"
если в конце скрипта добавить комментарий с помощью
//
то парсер выдаст ошибку
Quotesyntax error, unexpected '/', expecting $end
хотя на
/* В конце*/
парсер реагирует нормально


большой скрипт не напишешь, постоянно Stack underflow...

Victor Kirhenshtein

Quote from: SKYnv on September 22, 2012, 07:03:27 PM
1) пре инкремент
работает как декремент

Исправил.

Quote from: SKYnv on September 22, 2012, 07:03:27 PM
2) uint32 conversion
не работает данная конвертация

А можно пример скрипта?

Quote from: SKYnv on September 22, 2012, 07:03:27 PM
3) парсер и "//"
если в конце скрипта добавить комментарий с помощью
//
то парсер выдаст ошибку
Quotesyntax error, unexpected '/', expecting $end
хотя на
/* В конце*/
парсер реагирует нормально

Исправил.

Quote from: SKYnv on September 22, 2012, 07:03:27 PM
большой скрипт не напишешь, постоянно Stack underflow...

Это скорее всего следствие одной из ошибок. Можете привести пример скрипта, который дает stack underflow?

SKYnv

#2
Quote from: Victor Kirhenshtein on September 23, 2012, 12:40:08 PM
Это скорее всего следствие одной из ошибок. Можете привести пример скрипта, который дает stack underflow?

честно говоря, наверно с десяток скриптов всех и не упомнишь. Вот свежий пример, ошибка возникает из-за условия  i!=-10, вернее из-за отрицательного числа и не важно инкремент или декремент мы используем.

sub CheckPreInc()
{
for(i=0;i!=-10;i++)
{
println(i);
}
}

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


далее

Quote from: Victor Kirhenshtein
Quote from: SKYnv
2) uint32 conversion
не работает данная конвертация
А можно пример скрипта?

например такой

sub TestUInt32()
{
UvalMax=65535;
UvalMin=0;
uint32(UvalMax);
uint32(UvalMin);
resVal = false;
if ((typeof(UvalMax) == "uint32") && (typeof(UvalMin) == "uint32"))
{
println("uint32 range check ok");
}
else
{
println("uint32 range check failed");
      println(typeof(UvalMax));
      println(typeof(UvalMin));
    }
}


причем даже если мы сначала инициализируем её так

sub SmallTestUint32()
{
uint32(value);
value=1;
println(typeof(value));
return 0;
}


И даже так

sub SmallTestUint32()
{
uint32(value);
value=1;
println(typeof(uint32(value)));
return 0;
}


А можно мне для win32 собранные nxscript с нужными либами прикреплять сюда, а то до сборки под win32 у меня еще руки не дошли. Я себе сделал для удобства подсветку в EmEditor и интерпретатор прикрутил. Ну и на wiki немножко похозяйничал в разделе functions.
Ну и пока руки не дошли, но помоему sleep() работает несколько не адекватно.



Victor Kirhenshtein

Действительно, uint32(x) делал cast в int32. Опять copy/paste :)

Пре-инкремент у меня работает как надо - я это уже исправлял. В аттаче свежесобранный интерпретатор для 32 битного Windows.

SKYnv

#4
Quote from: Victor Kirhenshtein on September 24, 2012, 12:51:29 PM
Действительно, uint32(x) делал cast в int32. Опять copy/paste :)

Пре-инкремент у меня работает как надо - я это уже исправлял. В аттаче свежесобранный интерпретатор для 32 битного Windows.

Видимо в этом была беда в старой теме про отрицательные значения ))

сразу же уточнение, такой скрипт

sub SmallTestUint32()
{
value=1;
uint32(value);
println(typeof(value));
}

выдаст
Quoteint32
, но зачем он снова конвертирует значение? Если оно попадает в область uint32?

sub SmallTestUint32()
{
value=1;
uint32(value);
println(typeof(uint32(value)));
}

такой само собой
Quoteuint32
отрабатывает нормально.

зачем вообще нужна такая конвертация, если такой скрипт

sub SmallTestUint32()
{
value=-1;
uint32(value);
println(value);
           println(typeof(value));
println(typeof(uint32(value)));
println(value);
println(uint32(value));
return value;
}

выдаст
Quote
-1
int32
uint32
-1
4294967295

Victor Kirhenshtein

Конструкция вида


uint32(value);


смысла не имеет - возвращается преобразованное значение, которое выбрасывается. Тогда надо писать так:


value = uint32(value);


По сути type cast можно рассматривать как специальные функции - они принимают одно значение и возвращают преобразованное значение.

SKYnv

Quote from: Victor Kirhenshtein on September 24, 2012, 06:27:09 PM
Конструкция вида


uint32(value);


смысла не имеет - возвращается преобразованное значение, которое выбрасывается. Тогда надо писать так:


value = uint32(value);


По сути type cast можно рассматривать как специальные функции - они принимают одно значение и возвращают преобразованное значение.

ясно
stack underflow вроде пропал, пока не удалось воспроизвести.
буду баловаться дальше, спасибо.

SKYnv

netxms# date & nxadm -c "exec time"
понедельник,  1 октября 2012 г. 14:48:23 (YEKT)
1.9.2012, 14:48:23
INFO: Script finished with rc=0

сам скрипт
sub main()
{
println(localtime(time())->mday.".".localtime(time())->mon.".".localtime(time())->year.", ".localtime(time())->hour.":".localtime(time())->min.":".localtime(time())->sec);
}

требуется уточнить, баг это или ошибка на моей стороне.

SKYnv

round работает немножко некорректно.
пример из вики
Quoteround(2.378, 2) ->   2.38
то есть скрипт
sub main()
{
println round(2.378, 2);
}

но вернет следующее
Quotenetxmsd: exec test
2.378000
INFO: Script finished with rc=0


floor себя ведет также

sub main()
{
println floor(2.378);
}


Quotenetxmsd: exec test
2.000000
INFO: Script finished with rc=0

netxmsd:


это баг или фича? конечно можно отбрасывать лишнее left'ом но не кошерно же...

Victor Kirhenshtein

Странно. Написал вот такой тестовый скрипт:


C:\Source\NetXMS\x64\debug>cat test13.nxsl
if ($1 == null)
        $1 = 1.234567;

println "floor(" . $1 . ") = " . floor($1);
println "ceil(" . $1 . ") = " . ceil($1);
println "round(" . $1 . ") = " . round($1);
println "round(" . $1 . ", 2) = " . round($1, 2);


Результаты:



C:\Source\NetXMS\x64\debug>nxscript test13.nxsl
NetXMS Scripting Host  Version 1.2.6
Copyright (c) 2005-2012 Victor Kirhenshtein

floor(1.234567) = 1.000000
ceil(1.234567) = 2.000000
round(1.234567) = 1.000000
round(1.234567, 2) = 1.230000

C:\Source\NetXMS\x64\debug>nxscript test13.nxsl 2.378
NetXMS Scripting Host  Version 1.2.6
Copyright (c) 2005-2012 Victor Kirhenshtein

floor(2.378) = 2.000000
ceil(2.378) = 3.000000
round(2.378) = 2.000000
round(2.378, 2) = 2.380000

C:\Source\NetXMS\x64\debug>nxscript test13.nxsl 2.98
NetXMS Scripting Host  Version 1.2.6
Copyright (c) 2005-2012 Victor Kirhenshtein

floor(2.98) = 2.000000
ceil(2.98) = 3.000000
round(2.98) = 3.000000
round(2.98, 2) = 2.980000

C:\Source\NetXMS\x64\debug>


Т.е. round(x, 2) работает как описано. По поводу 0 в конце: после floor/ceil/round, тип данных у результата остается float - поэтомы и цифры после запятой. Это правильно, если число будет использоваться в дальнейших вычислениях. Для красивого форматирования числа можно использовать функцию format (http://wiki.netxms.org/wiki/NXSL:format), отдельно или как обертку вокруг ceil/floor/round.

Пример использования format:


C:\Source\NetXMS\x64\debug>cat test14.nxsl
if ($1 == null)
        $1 = 1.234567;

println "format(" . $1 . ", 1, 2) = " . format($1, 1, 2);
println "format(floor(" . $1 . "), 1, 0) = " . format(floor($1), 1, 0);

C:\Source\NetXMS\x64\debug>


Результаты:


C:\Source\NetXMS\x64\debug>nxscript test14.nxsl
NetXMS Scripting Host  Version 1.2.6
Copyright (c) 2005-2012 Victor Kirhenshtein

format(1.234567, 1, 2) = 1.23
format(floor(1.234567), 1, 0) = 1

C:\Source\NetXMS\x64\debug>nxscript test14.nxsl 17.5672334
NetXMS Scripting Host  Version 1.2.6
Copyright (c) 2005-2012 Victor Kirhenshtein

format(17.5672334, 1, 2) = 17.57
format(floor(17.5672334), 1, 0) = 17

C:\Source\NetXMS\x64\debug>


SKYnv

ясно, просто добивание отсутствующих разрядов нулями, несколько не то что ожидаешь. спасибо.
а использовать left не быстрее чем format?
Не, не быстрее, одинаково, но писать кода чуть меньше.

sub main()
{
if ($1 == null)
        $1 = 1.234567;

println format(round($1,2), 1, 2);
println typeof(format(round($1,2), 1, 2));
}

и
sub main()
{
if ($1 == null)
        $1 = 1.234567;

println left(round($1,2), 4);
println typeof(left(round($1,2), 4));
}


Quotenetxms# time nxadm -c "exec test"
1.23
real
INFO: Script finished with rc=0

0.000u 0.004s 0:00.10 0.0%      0+0k 0+0io 0pf+0w
netxms# time nxadm -c "exec test2"
1.23
real
INFO: Script finished with rc=0

0.000u 0.004s 0:00.10 0.0%      0+0k 0+0io 0pf+0w