nemerle
nemerle copied to clipboard
Компиляция с включенной оптимизацией выносит промежуточную переменную за тело цикла
using System;
using System.Console;
class cls
{
public Value : string
{
get { "aaaaa!" }
}
}
class cls1
{
public Item[num : int] : cls
{
get { if( num == 1 ) cls() else null }
}
}
module Program
{
Main() : void
{
def o = cls1();
foreach( i in array[1, 2] ) {
WriteLine(o[i]?.Value);
}
}
}
The output should be:
aaaaa!
Got in release:
aaaaa!
aaaaa!
In debug the output is correct.
Using reflector, it seems that in RELEASE mode the variable str is moved to FUNCTION scope instead of local loop scope. This is the cause of the error. So it must be a bug in Nemerle compiler or ?. macro
private static void Main()
{
string str = null; //<---- ERROR this variable should be LOCAL in LOOP
Program.cls1 cls2 = new Program.cls1();
for (list<int> tl = new list<int>.Cons(1, new list<int>.Cons(2, new list<int>.Cons(3, new list<int>.Cons(4, list<int>.Nil._N_constant_object)))); tl is list<int>.Cons; tl = tl)
{
int hd = ((list<int>.Cons) tl).hd;
tl = ((list<int>.Cons) tl).tl;
Program.cls cls = cls2[hd];
if (cls != null)
{
str = cls.Value;
}
Console.WriteLine(str);
}
}
This is how the program look correctly in DEBUG mode. The str variable is loop local. This issue is very troubling, what is the stability of the Nemerle compiler is someone decides to use it for production code?
private static void Main()
{
list<int> tl;
Program.cls1 cls = new Program.cls1();
for (list<int> list = new list<int>.Cons(1, new list<int>.Cons(2, new list<int>.Cons(3, new list<int>.Cons(4, list<int>.Nil._N_constant_object)))); list is list<int>.Cons; list = tl)
{
int hd = ((list<int>.Cons) list).hd;
tl = ((list<int>.Cons) list).tl;
int num2 = hd;
Program.cls cls2 = cls[num2];
string str2 = null;
if (cls2 != null)
{
str2 = cls2.Value;
}
string str = str2;
Console.WriteLine(str);
}
}
Release:
private static void Main()
{
string str = (string) null; // Release (!)
cls1 cls1 = new cls1();
int[] numArray1 = new int[2];
int index1 = 0;
int num1 = 1;
numArray1[index1] = num1;
int index2 = 1;
int num2 = 2;
numArray1[index2] = num2;
int[] numArray2 = numArray1;
int index3 = 0;
while (index3 < numArray2.Length)
{
int index4 = numArray2[index3];
cls cls = cls1[index4];
if (cls != null)
str = cls.Value;
Console.WriteLine(str);
checked { ++index3; }
}
}
Debug:
private static void Main()
{
cls1 cls1 = new cls1();
int[] numArray1 = new int[2];
int index1 = 0;
int num1 = 1;
numArray1[index1] = num1;
int index2 = 1;
int num2 = 2;
numArray1[index2] = num2;
int[] numArray2 = numArray1;
int index3 = 0;
while (index3 < numArray2.Length)
{
int index4 = numArray2[index3];
cls cls = cls1[index4];
string str = (string) null; // OK
if (cls != null)
str = cls.Value;
Console.WriteLine(str);
checked { ++index3; }
}
}
liviuu, don't panic, this is work correct
Main() : void
{
def o = cls1();
foreach( i in array[1, 2] ) {
def temp = o[i];
when( temp != null ) {
WriteLine(temp.Value);
}
}
}
I think, bug will fixed soon
So, the problem is the ?. macro that creates the temporary variable in wrong scope?