//
//	Test script for version 2.0
//

func Fatal()
{
	auto i;
	print(ntharg(0), ": ");
	for(i = 1; i <= nargs(); i++) {
		print(ntharg(i));
		if(i < nargs())
			print(" ");
	}
	print("\n");
	traceback();
	exit(1);
}

func CheckReturn(n)
{
	auto i;
	auto q;
	i = n;
	if(n > 0)
		return CheckReturn(n - 1);
	if(i != n)
		Fatal("CheckReturn: auto or arg corrupted.");
	return;
}

func CheckTransientVariables(n, name, v)
{
	auto i, j, k;
	if(n <= 0)
		return CheckReturn(1);
	if(v != 2)
		Fatal("CheckTransientVariables: bad v");
	return CheckTransientVariables(n - 1, name, v) + 1;
}

func CheckControlFlow(n)
{
	auto i;
	for(i = 0; i < n; i++)
		if(i == (n - 3))
			return 0;
	return 1;
}

func CheckSize(array, len)
{
	if(length(array) != len) {
		++Errors;
		print("CheckSize: expected ", len, " but got ",
			length(array), ".\n");
	}
}

func CheckArrays()
{
	auto a;
	auto i, j, k;

	a = fVector(500);
	CheckSize(a, 500);
	for(i = 0; i < 1000; i++)
		a[i] = 1000 - i;
	CheckSize(a, 1000);		
	a[$ + 1] = 0;
	CheckSize(a, 1001);		
	for(j = 0; j <= 1000; j++)
		if(a[j] != (1000 - j)) {
			++Errors;
			print("Bad array at j = ", j, " (", a[j], ")\n");
			return ;
		}

	//	the next block checks a bunch of nested '$' references
	//	to make sure that each picks up the size of the correct
	//	enclosing array.

	a[77] = Pi;
	ckval = a[77];
	k[13] = 5;
	k[14] = 987;
	j[33] = 77;
	j[38] = -234;
	if(a[j[$ - k[$ - 1]]] != ckval) {
		++Errors;
		print("Nested end-of-array items failed.\n");
		print("V = ", a[j[$ - k[$ - 1]]], "\n");
		return;
	}
}

func CheckfVector(vsize)
{
	auto x, y, z;

	x = fVector(vsize, 0);
	x = x + 3;
	y = x;
	y[:] = 0;
	if(size(y) != vsize) {
	    print("Bad size for y: ", size(y), " instead of ", vsize, "\n");
	    ++Errors;
	}
	y = y + Pi;
	z = x + y;
//	print("min(x) = ", min(x), "\n");
//	print("max(y) = ", max(y), "\n");
//	print("max(z) = ", max(z), "\n");
	z = z - sum(z)/length(z);
//	print("max(z) = ", max(z), "\n");
}

func CheckGetTokenLine()
{
	auto i, inf, j;
	auto l;
	auto sumo, sumi;

	inf = fopen("TextLines", "w");
	sumo = 0;
	for(j = 0; j < 10; j++) {
		for(i = 0; i < j + 5; i++) {
			l = i + 6 + j*i;
			sumo = sumo + l;
			fprint(inf, " ", l);
		}
		fprint(inf, "\n");
	}
	fclose(inf);

	inf = fopen("TextLines", "r");
	done = 0;
	l = 0;
	sumi = 0;
	while(done == 0) {
		lines = gettokenline(inf);
		if(lines == Nothing)
			++done;
		else {
			for(i = 0; i < length(lines); i++)
				sumi = sumi + strToNum(lines[i]);
		}
	}
	fclose(inf);
	if(sumo != sumi) {
		++Errors;
		print("getTokenLine error: ", sumo, " out, ", sumi, " in.\n");
	}
}

func CheckInternals()
{
	if(internals(1) != 0) {
		++Errors;
		print("internals(1) == ", internals(1), "\n");
	}
	return internals(0);
}

func CheckFlatten()
{
	auto f;

	f = flatten(1,2,3, flatten(4,5,6, flatten(7,8,9)),10);
//	print(f, "\n");
	f = flatten(1,2,3, flatten(4,5,6, flatten(7,8,9)),10, "Yo");
//	print(f, "\n");
}

func Begin()
{
	Records = 0;
	Errors = 0;
	CheckArrays();
 	CheckTransientVariables(10, "CheckTransientVariables", 2);
	CheckControlFlow(10);
	CheckfVector(193);
	CheckGetTokenLine();
	CheckFlatten();
	CheckInternals();
	if(Errors > 0)
		print("Language checks returned ", Errors, " errors.\n");
}

func OnLineHeader()
{
	print("Samples = ", LH.NumSmp, "\n");
	LH.HLH[size(LH.HLH)] = "Yo, Dude";
	NewHLH[0] = "Yo, Dude";
	NewHLH[size(NewHLH)] = "Here's more";
	LH.HLH = NewHLH;
	print("LH.HLH = ", LH.HLH, "\n");
	CheckInternals();
	Output(LH);
}

func OnTrace()
{
	auto t;
	++Records;
	if(Records < 2)
		print(length(Tr.Series), " samples in the first trace.\n");
	Tr.Series[:] = 0;
	Tr.Series = fVector(37);
	if(Records < 2)
		print(length(Tr.Series), " samples in the first trace.\n");
	CheckInternals();
	Output(Tr);
}

func End() {
	if(Records != 100)
		Fatal("End: bad record count.");
	if(Errors != 0)
		print(Errors, " errors.\n");
	else
		print("Ok.\n");
	CheckInternals();
	exit(Errors);
}

