diff --git a/squirrel/sqbaselib.cpp b/squirrel/sqbaselib.cpp
index f835cbf1..ddc6cf46 100644
--- a/squirrel/sqbaselib.cpp
+++ b/squirrel/sqbaselib.cpp
@@ -726,75 +726,93 @@ static bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger
return true;
}
-static bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)
-{
- SQInteger maxChild;
- SQInteger done = 0;
- SQInteger ret;
- SQInteger root2;
- while (((root2 = root * 2) <= bottom) && (!done))
- {
- if (root2 == bottom) {
- maxChild = root2;
- }
- else {
- if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
- return false;
- if (ret > 0) {
- maxChild = root2;
- }
- else {
- maxChild = root2 + 1;
- }
- }
+/*
+** The lua_auxsort code is adapted from from lua 5.1.5
+** {======================================================
+** Quicksort
+** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
+** Addison-Wesley, 1993.)
+** =======================================================
+*/
- if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
+static bool lua_auxsort (HSQUIRRELVM v, SQArray *arr, SQInteger l, SQInteger u,
+ SQInteger func) {
+ while (l < u) { /* for tail recursion */
+ SQInteger i, j, ret;
+ bool rc;
+ /* sort elements a[l], a[(l+u)/2] and a[u] */
+ if(!_sort_compare(v,arr->_values[u],arr->_values[l],func,ret))
+ return false;
+ if (ret < 0) /* a[u] < a[l]? */
+ _Swap(arr->_values[l],arr->_values[u]); /* swap a[l] - a[u] */
+ if (u-l == 1) break; /* only 2 elements */
+ i = (l+u)/2;
+ if(!_sort_compare(v,arr->_values[i],arr->_values[l],func,ret))
+ return false;
+ if (ret < 0) /* a[i]_values[i],arr->_values[l]);
+ else {
+ if(!_sort_compare(v,arr->_values[u],arr->_values[i],func,ret))
+ return false;
+ if (ret < 0) /* a[u]_values[i],arr->_values[u]);
+ }
+ if (u-l == 2) break; /* only 3 elements */
+ SQObjectPtr P = arr->_values[i]; /* Pivot */
+ _Swap(arr->_values[i],arr->_values[u-1]);
+ /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
+ i = l; j = u-1;
+ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
+ /* repeat ++i until a[i] >= P */
+ while ((rc = _sort_compare(v,arr->_values[++i],P,func,ret)) && (ret < 0)) {
+ if (i>u)
+ {
+ sq_throwerror(v, _SC("invalid order function for sorting"));
return false;
- if (ret < 0) {
- if (root == maxChild) {
- v->Raise_Error(_SC("inconsistent compare function"));
- return false; // We'd be swapping ourselve. The compare function is incorrect
- }
-
- _Swap(arr->_values[root],arr->_values[maxChild]);
- root = maxChild;
}
- else {
- done = 1;
+ }
+ if(!rc) return false;
+ /* repeat --j until a[j] <= P */
+ while ((rc = _sort_compare(v,P, arr->_values[--j],func,ret)) && (ret < 0)) {
+ if (j_values[i],arr->_values[j]);
}
- return true;
-}
-
-static bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger SQ_UNUSED_ARG(l), SQInteger SQ_UNUSED_ARG(r),SQInteger func)
-{
- SQArray *a = _array(arr);
- SQInteger i;
- SQInteger array_size = a->Size();
- for (i = (array_size / 2); i >= 0; i--) {
- if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
+ _Swap(arr->_values[u-1],arr->_values[i]); /* swap pivot (a[u-1]) with a[i] */
+ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
+ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
+ if (i-l < u-i) {
+ j=l; i=i-1; l=i+2;
}
-
- for (i = array_size-1; i >= 1; i--)
- {
- _Swap(a->_values[0],a->_values[i]);
- if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
+ else {
+ j=i+1; i=u; u=j-2;
}
- return true;
-}
-
-static SQInteger array_sort(HSQUIRRELVM v)
-{
- SQInteger func = -1;
- SQObjectPtr &o = stack_get(v,1);
- if(_array(o)->Size() > 1) {
- if(sq_gettop(v) == 2) func = 2;
- if(!_hsort(v, o, 0, _array(o)->Size()-1, func))
- return SQ_ERROR;
+ if(!lua_auxsort(v, arr, j, i, func)) /* call recursively for upper interval */
+ return false;
+ } /* repeat the routine for the larger one */
+ return true;
+}
+
+static SQRESULT array_sort(HSQUIRRELVM v) {
+ SQInteger func = -1;
+ SQObjectPtr &o = stack_get(v,1);
+ SQArray *arr = _array(o);
+ if(arr->Size() > 1) {
+ if(sq_gettop(v) == 2) func = 2;
+ if(!lua_auxsort(v, arr, 0, arr->Size()-1, func))
+ return SQ_ERROR;
- }
- sq_settop(v,1);
- return 1;
+ }
+ sq_settop(v,1);
+ return 1;
}
static SQInteger array_slice(HSQUIRRELVM v)
diff --git a/squirrel/sqclosure.h b/squirrel/sqclosure.h
index 66495b94..b204bb35 100644
--- a/squirrel/sqclosure.h
+++ b/squirrel/sqclosure.h
@@ -101,7 +101,7 @@ struct SQOuter : public CHAINABLE_OBJ
SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */
SQInteger _idx; /* idx in stack array, for relocation */
SQObjectPtr _value; /* value of outer after stack frame is closed */
- SQOuter *_next; /* pointer to next outer when frame is open */
+ SQOuter *_next_outer; /* pointer to next outer when frame is open */
};
//////////////////////////////////////////////
diff --git a/squirrel/sqvm.cpp b/squirrel/sqvm.cpp
index ecdcbb7d..30cf53b5 100644
--- a/squirrel/sqvm.cpp
+++ b/squirrel/sqvm.cpp
@@ -1632,10 +1632,10 @@ void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
target = SQObjectPtr(p);
return;
}
- pp = &p->_next;
+ pp = &p->_next_outer;
}
otr = SQOuter::Create(_ss(this), stackindex);
- otr->_next = *pp;
+ otr->_next_outer = *pp;
otr->_idx = (stackindex - _stack._vals);
__ObjAddRef(otr);
*pp = otr;
@@ -1695,7 +1695,7 @@ void SQVM::RelocateOuters()
SQOuter *p = _openouters;
while (p) {
p->_valptr = _stack._vals + p->_idx;
- p = p->_next;
+ p = p->_next_outer;
}
}
@@ -1704,7 +1704,7 @@ void SQVM::CloseOuters(SQObjectPtr *stackindex) {
while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
p->_value = *(p->_valptr);
p->_valptr = &p->_value;
- _openouters = p->_next;
+ _openouters = p->_next_outer;
__ObjRelease(p);
}
}
diff --git a/squirrel/sqvm.h b/squirrel/sqvm.h
index a75524da..de336e3f 100644
--- a/squirrel/sqvm.h
+++ b/squirrel/sqvm.h
@@ -168,7 +168,6 @@ typedef sqvector CallInfoVec;
CallInfo *ci;
SQUserPointer _foreignptr;
//VMs sharing the same state
- SQSharedState *_sharedstate;
SQInteger _nnativecalls;
SQInteger _nmetamethodscall;
SQRELEASEHOOK _releasehook;
diff --git a/tests/minctest.nut b/tests/minctest.nut
new file mode 100644
index 00000000..07f16cec
--- /dev/null
+++ b/tests/minctest.nut
@@ -0,0 +1,1335 @@
+//
+// MINCTEST - Minimal SquiLu Test Library
+// based on MINCTEST - Minimal Lua Test Library - 0.1.1
+// This is based on minctest.h (https://codeplea.com/minctest)
+//
+// Copyright (c) 2014, 2015, 2016 Lewis Van Winkle
+// Copyright (c) 2017 Domingo Alvarez Duarte
+//
+// http://CodePlea.com
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgement in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+
+// MINCTEST - Minimal testing library for C
+//
+//
+// Example:
+//
+//
+// #include "minctest.nut"
+// local l = minctest();
+//
+// l.run("test1", function(){
+// l.ok('a' == 'a'); //assert true
+// });
+//
+// l.run("test2", function(){
+// l.equal(5, 6); //compare integers
+// l.fequal(5.5, 5.6); //compare floats
+// });
+//
+// return l.results(); //show results
+//
+//
+// Hints:
+// All functions/variables start with the letter 'l'.
+//
+//
+
+function minctest()
+{
+ local self = {};
+ const LTEST_FLOAT_TOLERANCE = 1e-12; //1e-6; 0.001;
+
+
+ local ltests = 0;
+ local lfails = 0;
+ local start_clock = clock();
+
+
+ self.results <- function()
+ {
+ local total_time = floor((clock() - start_clock) * 1000) + "ms";
+ if (lfails == 0)
+ print("ALL TESTS PASSED (" + ltests + "/" + ltests + ") " + total_time);
+ else
+ print("SOME TESTS FAILED (" + (ltests-lfails) + "/" + ltests + ") " + total_time);
+
+ print("\n");
+ return lfails != 0;
+ }
+
+
+ self.run <- function(name, testfunc)
+ {
+ local ts = ltests;
+ local fs = lfails;
+ local lclock = clock();
+ local msg = format("\t%-24s", name);
+ print(msg);
+ testfunc();
+ msg = format("pass: %2d fail: %2d %4dms\n",
+ (ltests-ts)-(lfails-fs), lfails-fs,
+ floor((clock() - lclock) * 1000));
+ if(lfails) print("\n");
+ print(msg);
+ }
+
+ self.ok <- function(test)
+ {
+ ++ltests;
+ if ( ! test )
+ {
+ ++lfails;
+ local stack_info = getstackinfos(2);
+ print(format("\n%s:%d:0 error",
+ stack_info.src,
+ stack_info.line));
+ }
+ }
+
+ self.equal <- function(a, b)
+ {
+ ++ltests;
+ if (a != b)
+ {
+ ++lfails;
+ local stack_info = getstackinfos(2);
+ print(format("%s:%d (%d != %d)\n",
+ stack_info.src,
+ stack_info.line,
+ a, b));
+ }
+ }
+
+ self.fequal <- function(a, b)
+ {
+ ++ltests;
+ if (fabs(a - b) > LTEST_FLOAT_TOLERANCE)
+ {
+ ++lfails;
+ local stack_info = getstackinfos(2);
+ print(format("%s:%d (%f != %f)\n",
+ stack_info.src,
+ stack_info.line,
+ a, b));
+ }
+ }
+
+ self.fails <- function() {return lfails;}
+
+ return self;
+}
+
+class Dad
+{
+ _n = null;
+ constructor(n){ _n = n;}
+
+ function print() {printf("%d\n", _n);}
+ function onlyForFriends(){}
+ function onlyForUs(){}
+};
+
+local sqt = minctest();
+
+local globals = getroottable();
+
+sqt.run("closures", function(){
+
+ local A = 0, B = {g=10}
+ local f = function(x)
+ {
+ local a = []
+ for(local i=1; i < 1000; ++i)
+ {
+ local y = 0
+ {
+ a.append(function () {++B.g; y += x; return y+A;});
+ }
+ }
+ local dummy = function () {return a[A];}
+ collectgarbage()
+ A = 1;
+ sqt.ok(dummy() == a[1]);
+ A = 0;
+ //print("a[0]", a[0]())
+ sqt.ok(a[0]() == x)
+ sqt.ok(a[2]() == x)
+ collectgarbage()
+ sqt.ok(B.g == 12)
+ return a
+ }
+
+ local a = f(10)
+
+ // testing closures with 'for' control variable
+ a = []
+ for(local i=0; i < 10; ++i)
+ {
+ local lv = i;
+ a.append({set = function(x){ lv=x; }, get = function (){ return lv; }})
+ if( i == 2 ) break;
+ }
+ sqt.ok(a.len() == 3)
+ sqt.ok(a[0].get() == 0)
+ a[0].set(10)
+ sqt.ok(a[0].get() == 10)
+ sqt.ok(a[1].get() == 1)
+ a[1].set('a')
+ sqt.ok(a[1].get() == 'a')
+ //a[2].set(2)
+ sqt.ok(a[2].get() == 2)
+
+ a = []
+ foreach( i, k in ['a', 'b'])
+ {
+ local li = i
+ local lk = k
+ a.append( {set = function(x, y) {li=x; lk=y},
+ get = function () {return [li, lk];}} )
+ if( i == 2 ) break;
+ }
+ a[0].set(10, 20)
+ local rs = a[1].get()
+ sqt.ok(rs[0] == 1 && rs[1] == 'b')
+ rs = a[0].get()
+ sqt.ok(rs[0] == 10 && rs[1] == 20)
+ a[1].set('a', 'b')
+ rs = a[1].get()
+ sqt.ok(rs[0] == 'a' && rs[1] == 'b')
+
+ // testing closures with 'for' control variable x break
+ for(local i=1; i <= 3; ++i)
+ {
+ local li = i
+ f = function () { return li;}
+ break
+ }
+ sqt.ok(f() == 1)
+
+ foreach( k, v in ["a", "b"])
+ {
+ local lk = k, lv = v
+ f = function () {return [lk, lv]; }
+ break
+ }
+ sqt.ok(([f()])[0][0] == 0)
+ sqt.ok(([f()])[0][1] == "a")
+
+
+ // testing closure x break x return x errors
+
+ local b
+ f = function (x)
+ {
+ local first = 1
+ while( 1 ) {
+ if( x == 3 && ! first ) return
+ local la = "xuxu"
+ b = function (op, y=0) {
+ if( op == "set" )
+ la = x+y
+ else
+ return la
+ }
+ if( x == 1 ) { break }
+ else if( x == 2 ) return
+ else if( x != 3 ) throw("x != 3")
+
+ first = null
+ }
+ }
+
+ for(local i=1; i <= 3; ++i) {
+ f(i)
+ sqt.ok(b("get") == "xuxu")
+ b("set", 10); sqt.ok(b("get") == 10+i)
+ b = null
+ }
+
+ //pcall(f, 4);
+ try{ f(4);}catch(e){}
+ sqt.ok(b("get") == "xuxu")
+ b("set", 10); sqt.ok(b("get") == 14)
+
+ // testing multi-level closure
+ local w
+ f = function(x)
+ {
+ return function (y)
+ {
+ return function (z) {return w+x+y+z;}
+ }
+ }
+
+ local y = f(10)
+ w = 1.345
+ sqt.ok(y(20)(30) == 60+w)
+
+ // test for correctly closing upvalues in tail calls of vararg functions
+ local function t ()
+ {
+ local function c(a,b) {sqt.ok(a=="test" && b=="OK") }
+ local function v(f, ...) {c("test", f() != 1 && "FAILED" || "OK") }
+ local lx = 1
+ return v(function() {return lx;})
+ }
+ t()
+
+});
+
+sqt.run("calls", function(){
+
+ // get the opportunity to test "type" too ;)
+ local Klass = class {};
+ local aklass = Klass();
+
+ sqt.ok(type(1<2) == "bool")
+ sqt.ok(type(true) == "bool" && type(false) == "bool")
+ sqt.ok(type(null) == "null")
+ sqt.ok(type(-3) == "integer")
+ sqt.ok(type(-3.14) == "float")
+ sqt.ok(type("x") == "string")
+ sqt.ok(type({}) == "table")
+ sqt.ok(type(type) == "function")
+ sqt.ok(type(Klass) == "class")
+ sqt.ok(type(aklass) == "instance")
+
+ sqt.ok(type(sqt.ok) == type(print))
+ local f = null
+ f = function (x) {return a.x(x);}
+ sqt.ok(type(f) == "function")
+
+ // testing local-function recursion
+ local fact = false
+ {
+ local res = 1
+ local lfact;
+ lfact = function(n)
+ {
+ if( n==0 ) return res
+ else return n*lfact(n-1)
+ }
+ sqt.ok(lfact(5) == 120)
+ }
+ sqt.ok(fact == false)
+
+ // testing declarations
+ local a = {i = 10}
+ local self = 20
+ a.x <- function(x) {return x+this.i;}
+ a.y <- function(x) {return x+self;}
+
+ sqt.ok(a.x(1)+10 == a.y(1))
+
+ a.t <- {i=-100}
+ a["t"].x <- function (a,b) {return this.i+a+b;}
+
+ sqt.ok(a.t.x(2,3) == -95)
+
+ {
+ local la = {x=0}
+ la.add <- function(x) {this.x = this.x+x; la.y <- 20; return this; }
+ sqt.ok(la.add(10).add(20).add(30).x == 60 && la.y == 20)
+ }
+
+ a = {b={c={}}}
+
+ a.b.c.f1 <- function(x) {return x+1;}
+ a.b.c.f2 <- function(x,y) {this[x] <- y;}
+ sqt.ok(a.b.c.f1(4) == 5)
+ a.b.c.f2("k", 12); sqt.ok(a.b.c.k == 12)
+
+ local t = null // 'declare' t
+ f = function(a,b,c=null, e=null) {local d = 'a'; t=[a,b,c,d];}
+
+ f( // this line change must be valid
+ 1,2)
+ sqt.ok(t[0] == 1 && t[1] == 2 && t[2] == null && t[3] == 'a')
+
+ f(1,2, // this one too
+ 3,4)
+ sqt.ok(t[0] == 1 && t[1] == 2 && t[2] == 3 && t[3] == 'a')
+
+ // fixed-point operator
+ local Y = function (le)
+ {
+ local function la (f)
+ {
+ return le(function (x) {return f(f)(x);})
+ }
+ return la(la)
+ }
+
+
+ // non-recursive factorial
+
+ local F = function (f)
+ {
+ return function (n)
+ {
+ if( n == 0 ) return 1
+ else return n*f(n-1)
+ }
+ }
+
+ local fat = Y(F)
+
+ sqt.ok(fat(0) == 1 && fat(4) == 24 && Y(F)(5)==5*Y(F)(4))
+
+ local function g (z)
+ {
+ local function lf (a,b,c,d)
+ {
+ return function (x,y) {return a+b+c+d+a+x+y+z;}
+ }
+ return lf(z,z+1,z+2,z+3)
+ }
+
+ f = g(10)
+ sqt.ok(f(9, 16) == 10+11+12+13+10+9+16+10)
+
+ Y, F, f = null
+
+ try { assert(true); sqt.ok(true);} catch(e) {sqt.ok(false);};
+ try { assert(true, "opt msg"); sqt.ok(true);} catch(e) {sqt.ok(false);};
+ try { assert(false); sqt.ok(false);} catch(e) {sqt.ok(true);};
+ try { assert(false, "opt msg"); sqt.ok(false);} catch(e) {sqt.ok(e == "opt msg");};
+
+ local bugRecursionLocal;
+ bugRecursionLocal = function(str, num=666, car=777){
+ if(str == "recurse") return bugRecursionLocal("recurring with recurse", 5);
+ return str + num;
+ }
+
+ sqt.ok(bugRecursionLocal("dad") == "dad666");
+ sqt.ok(bugRecursionLocal("recurse") == "recurring with recurse5");
+
+ local function f1(){ return "f1";}
+ local function f2(){ return "f2";}
+ local function f3(f=f2){ return "f3" + f();}
+
+ sqt.ok(f3() == "f3f2");
+
+ local function f4(f=f2){ return "f4" + type(f);}
+
+ sqt.ok(f4() == "f4function");
+
+ local ary = ["blue"]
+ local function f5(s, f=ary){ return "f5" + s + type(f);}
+
+ sqt.ok(f5("ded") == "f5dedarray");
+
+ local ncount = 0;
+ local nested;
+ nested = function(p=88, q=66)
+ {
+ ++ncount;
+ local result = ncount + ":" + p + ":" + q;
+ local function ni(x=99)
+ {
+ result += ":" + x;
+ }
+ ni();
+ if(p==88) result += "::" + nested(22);
+ return result;
+ }
+
+ sqt.ok(nested() == "1:88:66:99::2:22:66:99");
+ sqt.ok(nested("n") == "3:n:66:99");
+
+});
+
+sqt.run("sort", function(){
+ local function check (a, f=null)
+ {
+ f = f || function (x,y) {return x 2; --n) sqt.ok(! f(a[n], a[n-1]))
+ }
+
+ local a = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"]
+
+ a.sort()
+ check(a)
+
+ limit <- 5000
+ //if( "_soft" in globals) limit = 5000
+
+ a = []
+ for(local i=0; i < limit; ++i) a.append(rand())
+
+ a.sort()
+ check(a)
+
+ a.sort()
+ check(a)
+
+ a = []
+ for(local i=0; i < limit; ++i) a.append(rand())
+
+ local li=0
+ a.sort(function(x,y) {li=li+1; return y<=>x;})
+ check(a, function(x,y) {return y 2));
+ sqt.ok(!(2 > 2));
+ sqt.ok(2 > 1);
+ sqt.ok(!(1 >= 2));
+ sqt.ok(2 >= 2);
+ sqt.ok(2 >= 1);
+ sqt.ok(!(0 < -0));
+ sqt.ok(!(-0 < 0));
+ sqt.ok(!(0 > -0));
+ sqt.ok(!(-0 > 0));
+ sqt.ok(0 <= -0);
+ sqt.ok(-0 <= 0);
+ sqt.ok(0 >= -0);
+ sqt.ok(-0 >= 0);
+
+ sqt.ok((8 / 2) == 4);
+ sqt.fequal((12.34 / -0.4), -30.85);
+ //sqt.ok(!isfinite(3 / 0)); // == infinity);
+ //sqt.ok(!isfinite(-3 / 0)); // == -infinity);
+ //sqt.ok(isnan(0 / 0));
+ //sqt.ok(isnan(-0 / 0));
+ //sqt.ok(!isfinite(3 / -0)); // == -infinity);
+ //sqt.ok(!isfinite(-3 / -0)); // == infinity);
+ //sqt.ok(isnan(0 / -0));
+ //sqt.ok(isnan(-0 / -0));
+
+ sqt.ok(123 == 123);
+ sqt.ok(123 != 124);
+ sqt.ok(-3 != 3);
+ sqt.ok(0 == -0);
+ sqt.ok(123 != "123");
+ sqt.ok(1 == true);
+ sqt.ok(0 == false);
+ //sqt.ok(1 !== true);
+ //sqt.ok(0 !== false);
+
+ sqt.ok((0 & 0) == 0);
+ sqt.ok((0xaaaaaaaa & 0x55555555) == 0);
+ //sqt.ok((0xf0f0f0f0 & 0x3c3c3c3c) == 808464432);
+ //sqt.ok((0xffffffff & 0xffffffff) == 4294967295);
+
+ try{1 & false, sqt.ok(0)} catch(e) {sqt.ok(1);} // expect runtime error: Right operand must be a number.
+
+ sqt.ok((0 << 0) == 0);
+ sqt.ok((1 << 0) == 1);
+ sqt.ok((0 << 1) == 0);
+ sqt.ok((1 << 1) == 2);
+ //sqt.ok((0xffffffff << 0) == 4294967295);
+
+ sqt.ok((0 >> 0) == 0);
+ sqt.ok((1 >> 0) == 1);
+ sqt.ok((0 >> 1) == 0);
+ sqt.ok((1 >> 1) == 0);
+/*
+ if(_intsize_ == 8)
+ {
+ sqt.ok((0xaaaaaaaa << 1) == 5726623060);
+ sqt.ok((0xf0f0f0f0 << 1) == 8084644320);
+ sqt.ok((0xaaaaaaaa >> 1) == 1431655765);
+ sqt.ok((0xf0f0f0f0 >> 1) == 2021161080);
+ sqt.ok((0xffffffff >> 1) == 2147483647);
+ }
+ else
+ {
+ sqt.ok((0xaaaaaaaa << 1) == 1431655764);
+ sqt.ok((0xf0f0f0f0 << 1) == -505290272);
+ sqt.ok((0xaaaaaaaa >> 1) == -715827883);
+ sqt.ok((0xf0f0f0f0 >> 1) == -126322568);
+ sqt.ok((0xffffffff >> 1) == -1);
+ }
+*/
+ sqt.ok((0 ^ 0) == 0);
+ sqt.ok((1 ^ 1) == 0);
+ sqt.ok((0 ^ 1) == 1);
+ sqt.ok((1 ^ 0) == 1);
+ //sqt.ok((0xaaaaaaaa ^ 0x55555555) == 4294967295);
+ //sqt.ok((0xf0f0f0f0 ^ 0x3c3c3c3c) == 3435973836);
+ //sqt.ok((0xffffffff ^ 0xffffffff) == 0);
+
+ //sqt.ok((~0) == 4294967295);
+ //sqt.ok((~1) == 4294967294);
+ //sqt.ok((~23) == 4294967272);
+ //sqt.ok((~0xffffffff) == 0);
+ //sqt.ok((~1.23) == 4294967294);
+ //sqt.ok((~0.00123) == 4294967295);
+ //sqt.ok((~345.67) == 4294966950);
+
+ sqt.ok((0 | 0) == 0);
+ //sqt.ok((0xaaaaaaaa | 0x55555555) == 4294967295);
+ //sqt.ok((0xcccccccc | 0x66666666) == 4008636142);
+ //sqt.ok((0xffffffff | 0xffffffff) == 4294967295);
+
+ local a = 3;
+ sqt.ok((5 - 3) == 2);
+ sqt.fequal((3.1 - 0.24), 2.86);
+ sqt.ok((3 - 2 - 1) == 0);
+ sqt.ok(-a == -3);
+
+ sqt.ok((1 + 2) == 3);
+ sqt.ok((12.34 + 0.13) == 12.47);
+ sqt.ok((3 + 5 + 2) == 10);
+
+ sqt.ok((5 % 3) == 2);
+ sqt.ok((10 % 5) == 0);
+ sqt.ok((-4 % 3) == -1);
+ sqt.ok((4 % -3) == 1);
+ sqt.ok((-4 % -3) == -1);
+ sqt.ok((-4.2 % 3.1) == -1.1);
+ sqt.ok((4.2 % -3.1) == 1.1);
+ sqt.ok((-4.2 % -3.1) == -1.1);
+ sqt.ok((13 % 7 % 4) == 2);
+ sqt.ok((13 + 1 % 7) == 14);
+
+ sqt.ok((5 * 3) == 15);
+ sqt.ok((12.34 * 0.3) == 3.702);
+ //10000000000000004 < 32BITS
+ //10000000000000002 < 64BITS
+ //print(format("%.17g", 1e16 + 2.9999) , "10000000000000002");
+ //if(_intsize_ == 8)
+ sqt.ok(format("%.17g", 1e16 + 2.9999) == "10000000000000002");
+ //else sqt.ok(format("%.17g", 1e16 + 2.9999) == "10000000000000004");
+
+});
+
+sqt.run("enum", function(){
+ enum e1 {one=1, two};
+ sqt.ok(e1.one == 1);
+ sqt.ok(e1.two == 2);
+
+ enum e2 {one=-1, two, three};
+ sqt.ok(e2.one == -1);
+ sqt.ok(e2.two == 0);
+ sqt.ok(e2.three == 1);
+
+ enum e3 {one=-1, two, three, nine=9, ten};
+ sqt.ok(e3.one == -1);
+ sqt.ok(e3.two == 0);
+ sqt.ok(e3.three == 1);
+ sqt.ok(e3.nine == 9);
+ sqt.ok(e3.ten == 10);
+});
+
+sqt.run("constants", function(){
+ const ONE = 1;
+ const STR = "string";
+
+ sqt.ok(ONE == 1);
+ sqt.ok(STR == "string");
+});
+
+sqt.run("class", function(){
+
+ class Comparable {
+ constructor(n)
+ {
+ name = n;
+ }
+
+ function _typeof() {return "Comparable";};
+
+ function _cmp(other)
+ {
+ if(nameother.name) return 1;
+ return 0;
+ }
+ static function st() {return "st";};
+ name = null;
+ id = 0;
+ static count = 0;
+ }
+ local a = Comparable("Alberto");
+ local b = Comparable("Wouter");
+ local c = Comparable("Alberto");
+ sqt.ok(a < b);
+ sqt.ok(b > a);
+ sqt.ok(a.id == 0);
+ sqt.ok(Comparable.count == 0);
+ sqt.ok(a.count == 0);
+ sqt.ok(Comparable.st() == "st");
+ sqt.ok(a.st() == "st");
+ sqt.ok(typeof(a) == "Comparable");
+ sqt.ok( c == a );
+ //sqt.ok( c !== a );
+
+});
+
+sqt.run("globals", function(){
+
+ //sqt.ok( obj_clone(3) == 3 );
+ //sqt.ok( obj_clone(3.4) == 3.4 );
+ //sqt.ok( obj_clone("str") == "str" );
+
+});
+
+return sqt.results(); //show results