All the old bugfixes and patches
https://github.com/raysilent/lslforge/commit/7ae61d900fe16b072d261518cefb2948a9c0e112 needs to be tested extensively because of https://github.com/raysilent/lslforge/blob/7ae61d900fe16b072d261518cefb2948a9c0e112/lslforge/haskell/LslForge.cabal#L30 (does it compile?)
I'm also not sure about https://github.com/raysilent/lslforge/compare/master...RayZopf:master#diff-c36d07f78ea57cd86da4be9be4be3014R123
less parentheses/brackets
- make it work on OSGrid
- fix cast of cast
state version in script output
fixes on handling variables and functions
json support and fix for string issue
update and sync version number
regarding haskell packages / compile see https://github.com/RayZopf/LSLForge_patched and esp. https://code.google.com/p/lslforge/issues/detail?id=40#c7
There is a math bug in this version with the code optimization:
llSleep((0.06 - (llGetTime() - time)) * llGetRegionTimeDilation()); is incorrectly optimized as: llSleep((6.0e-2 - llGetTime() - time) * llGetRegionTimeDilation());
Messing up the operation order 1 - (5 - 4) = 0 1 - 5 - 4 = -8
I know about one other bug:
(float-variable = number-a / number-b) get's calculated to (f-v = 0); use f-v = a.n / b.m not (val = 4 / 5) but (val = 4.0 / 5.0)
have not tested if the bug is in main LSLForge too, or if only this patched version exposes this miscalculation
Haven't seen the problem on raysilent's branch.
I'm scary to merge at this point
We have to compile and release this master branch though, so everyone enjoys it while we are testing these Haskell modifications. How about that?
what do you think about cherry-picking the last commit/the changes in there?
- add version number stamp to Render.hs (lsl output)
- sync version number for Render.hs and LslForge.hs
- sync and update version number in Render.hs, LslForge.hs and LslForge.cabal
https://github.com/RayZopf/lslforge-raysilent/commit/067cb56e40bae6282e6b5c7b0a9a981511c701c0 https://github.com/RayZopf/lslforge-raysilent/commit/4c1a4978171840e5b6a475d4cb49527aaebde532
this could also be done manually
I agree that we need someone who can code in Haskell, as the original author of those patches is not available
script to test for both issues
//Test the modified LSLForge.exe
//
float a = 99.0;
float b = 1.0;
float c = 2.0;
float a1 = 99;
float b1 = 1;
float c1 = 2;
integer ia = 99;
integer ib = 3;
integer ic = 2;
integer id = 1;
integer ia1 = 99;
integer ib1 = 3;
integer ic1 = 2;
integer id1 = 1;
integer ia2 = 99;
integer ib2 = 3;
integer ic2 = 2;
integer id2 = 1;
integer ia3 = 99;
integer ib3 = 3;
integer ic3 = 2;
integer id3 = 1;
integer returnValue_ic()
{
// variable not touched/changed, will be replaced/removed
return ic;
}
integer returnValue_ic1()
{
// this way the variable gets not optimized away
ic1 = 2;
return ic1;
}
integer returnValue_ic2()
{
// this way the variable gets not optimized away
ic2 = 2;
return ic2;
}
integer returnValue_ic3()
{
// variable not touched/changed, will be replaced/removed
return ic3;
}
default
{
state_entry()
{
// float variable handling
// both should be 0.5
// when error, bad float would be 0
a = b / c;
a1 = b1 / c1; //ERROR
if (a == a1 && 0.5 == a) llSay(0, "float variable handling is fine, result =" + (string)a1 + " each");
else llSay(0, "bad float =" + (string)a1 + " should be same as good float =" + (string)a + "; EXPECTED VALUE IS 0.5");
// subtration and parenthesis handling
// all should be 2
// when error, bad sub/par would be 0
// basic math test
ia = ib -(ic - id); //gets completely calculated/optimized as no variable is touched/changed
ia1 = ib1 -(ic1 - id1); //ERROR, even with variables only - variable could not get replaced by value before optimizing?
ia2 = ib2 -1*(ic2 - id2); //test workaround
ia3 = ib3 -1*(ic3 - id3); //test workaround and optimization/calculation
if (ia == ia1 && ia == ia2 && ia2 == ia3 && 2 == ia) llSay(0, "basic math: sub/par handling is fine, result =" + (string)ia1 + "each");
else llSay(0, "basic math: bad sub/par =" + (string)ia1 + " and " +(string)ia2 + " - " + (string)ia3 + ", should be same as good sub/par =" + (string)ia + "; EXPECTED VALUE IS 2");
// full test
ia = ia1 = ia2= 99;
ia = ib -(returnValue_ic() - id); //gets completely calculated/optimized as no variable is touched/changed
ia1 = ib1 -(returnValue_ic1() - id1); //ERROR
ia2 = ib2 -1*(returnValue_ic2() - id2); //test workaround
ia3 = ib3 -1*(returnValue_ic3() - id3); //test workaround and optimization/calculation
if (ia == ia1 && ia == ia2 && ia2 == ia3 && 2 == ia) llSay(0, "full: sub/par handling is fine, result =" + (string)ia1 + "each");
else llSay(0, "full: bad sub/par =" + (string)ia1 + " and " +(string)ia2 + " - " + (string)ia3 + ", should be same as good sub/par =" + (string)ia + "; EXPECTED VALUE IS 2");
}
}
// LSL script generated - patched Render.hs (0.1.6.2): LSLForge-debug.lslp Sat Feb 20 04:48:40 Mitteleuropäische Zeit 2016
//Test the modified LSLForge.exe
//
float a = 99.0;
float a1 = 99;
integer ia = 99;
integer ia1 = 99;
integer ic1 = 2;
integer ia2 = 99;
integer ic2 = 2;
integer ia3 = 99;
integer returnValue_ic1(){
ic1 = 2;
return ic1;
}
integer returnValue_ic2(){
ic2 = 2;
return ic2;
}
default {
state_entry() {
a = 0.5;
a1 = 0;
if (a == a1 && 0.5 == a) llSay(0,"float variable handling is fine, result =" + (string)a1 + " each");
else llSay(0,"bad float =" + (string)a1 + " should be same as good float =" + (string)a + "; EXPECTED VALUE IS 0.5");
ia = 2;
ia1 = 3 - ic1 - 1;
ia2 = 3 - 1 * (ic2 - 1);
ia3 = 2;
if (ia == ia1 && ia == ia2 && ia2 == ia3 && 2 == ia) llSay(0,"basic math: sub/par handling is fine, result =" + (string)ia1 + "each");
else llSay(0,"basic math: bad sub/par =" + (string)ia1 + " and " + (string)ia2 + " - " + (string)ia3 + ", should be same as good sub/par =" + (string)ia + "; EXPECTED VALUE IS 2");
ia = ia1 = ia2 = 99;
ia = 2;
ia1 = 3 - returnValue_ic1() - 1;
ia2 = 3 - 1 * (returnValue_ic2() - 1);
ia3 = 2;
if (ia == ia1 && ia == ia2 && ia2 == ia3 && 2 == ia) llSay(0,"full: sub/par handling is fine, result =" + (string)ia1 + "each");
else llSay(0,"full: bad sub/par =" + (string)ia1 + " and " + (string)ia2 + " - " + (string)ia3 + ", should be same as good sub/par =" + (string)ia + "; EXPECTED VALUE IS 2");
}
}
Guys, let's work on 0.1.7, attempt to prepare it for release. Then we'll get back to this issue.
Please use https://github.com/raysilent/lslforge/issues/2 for communications on 0.1.7.
Regarding the "float variable handling" ((float-variable = number-a / number-b) get's calculated to (f-v = 0);):
I don't see a bug, because the operation is done exectly like LSL behaves inworld:
float fv=1/2; both operants are integer -> the division is an integer division (integer division : 1/2=0) the integer result is then magicly cast to a float, because the left side (fv) is an float and the right side is an integer.
Try the following script inworld:
default {
state_entry() {
float fv;
//integer division (because both operands are integer)
//casting to float after the division
fv=1/5;
llOwnerSay((string)fv); //0.000000
//float division (because at least one operand is a float)
fv=4.0/5;
llOwnerSay((string)fv); //0.800000
//float division (because at least one operand is a float)
fv=4/5.0;
llOwnerSay((string)fv); //0.800000
//float division (because at least one operand is a float)
fv=4.0/5.0;
llOwnerSay((string)fv); //0.800000
}
}
tested float/autocast again - see attached script LSLForge-debug.txt
basically the LSLForge.exe in this PR does:
LSLForge error only - autocasts given values, disregardes type of used variable in calculation
i.e. float c = 3 used in float b = 10 / c is treated as integer value, resulting in b = 3.000000
Mono (and LSLForge):
used values are of type integer, so result becomes integer too - before putting into float variable
i.e. calculating float a2 = 10 / 3 = 3.000000
do I have to like that?
Mono (and LSLForge): used values are of type integer, so result becomes integer too - before putting into float variable i.e. calculating float a2 = 10 / 3 = 3.000000
do I have to like that?
I don't know ;) .. But I wouldn't call it an error or bug. I guess it depends on the point of view .. you could also call it a feature, because an integer division is much faster than a float division. (And because both operants are integers, the interpreter could/should guess you would like to perform an integer division)
I wouldn't merge that >_>
float a2 = 10 / 3 (= 3.000000) is calculated inworld
I can live with this:
//As a workaround //Never ever trust an autocast, if you want a number to be an float, write it as a float
and given the findings, I would not call it a workaround - esp. as it is needed for any LSL script to run correctly (https://github.com/raysilent/lslforge/pull/1#issuecomment-186832445)
That way LSLForge autocasting float c = 3 to integer value 3 won't happen too.
Also I cannot imagine any other operation where LSLForge inadvertently would optimize/cast a value as integer...
BTW. LSO gives same results as Mono :D
just checked - LSLForge previous to above changes also does autocast integer values within float variables to integer
float a1 = 99;
float b1 = 1;
float c1 = 2;
a1 = b1 / c1;
= 0 (integer)
this is still different to Mono / inworld variable autocast handling- but this behaviour has not been changed by applied patch! try with the different LSLForge revisions and confirm, please
latest win32 exe files for testing, unstripped and stripped version
also one single change that I have not commited yet old:
if assoc ex0 && assoc ex1 then True
else False
--may give a few too much parenthesisas, as not comparing e0 and ex1 e.g. (Sub _ _) == (Sub _ _)
--would be no need for parenthesis when e.g (Sub _ _) and (Lt _ _) except for precedence
--but be carefull with Lt, Gt, Le, Ge
now:
if assoc ex0 && assoc ex1 && (prec ex0 == prec ex1) then True
else False
@PellSmit could you take a look into this pull request, please? I believe most of the major enhancements / patches were done by you, I only contributed text, description and a fix to that parenthesis code
@RayZopf,I don't have enough time to do it. Sorry, I think I'll make you want for long time...