lua

A copy of the Lua development repository
Log | Files | Refs | README

constructs.lua (9946B)


      1 -- $Id: testes/constructs.lua $
      2 -- See Copyright Notice in file all.lua
      3 
      4 ;;print "testing syntax";;
      5 
      6 local debug = require "debug"
      7 
      8 
      9 local function checkload (s, msg)
     10   assert(string.find(select(2, load(s)), msg))
     11 end
     12 
     13 -- testing semicollons
     14 local a
     15 do ;;; end
     16 ; do ; a = 3; assert(a == 3) end;
     17 ;
     18 
     19 
     20 -- invalid operations should not raise errors when not executed
     21 if false then a = 3 // 0; a = 0 % 0 end
     22 
     23 
     24 -- testing priorities
     25 
     26 assert(2^3^2 == 2^(3^2));
     27 assert(2^3*4 == (2^3)*4);
     28 assert(2.0^-2 == 1/4 and -2^- -2 == - - -4);
     29 assert(not nil and 2 and not(2>3 or 3<2));
     30 assert(-3-1-5 == 0+0-9);
     31 assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0);
     32 assert(-3%5 == 2 and -3+5 == 2)
     33 assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33");
     34 assert(not(2+1 > 3*1) and "a".."b" > "a");
     35 
     36 assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4)
     37 assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4)
     38 assert(0xF0 & 0x0F + 1 == 0x10)
     39 
     40 assert(3^4//2^3//5 == 2)
     41 
     42 assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3))
     43 
     44 assert(not ((true or false) and nil))
     45 assert(      true or false  and nil)
     46 
     47 -- old bug
     48 assert((((1 or false) and true) or false) == true)
     49 assert((((nil and true) or false) and true) == false)
     50 
     51 local a,b = 1,nil;
     52 assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
     53 local x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
     54 x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
     55 
     56 local x, y = 1, 2;
     57 assert((x>y) and x or y == 2);
     58 x,y=2,1;
     59 assert((x>y) and x or y == 2);
     60 
     61 assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
     62 
     63 do   -- testing operators with diffent kinds of constants
     64   -- operands to consider:
     65   --  * fit in register
     66   --  * constant doesn't fit in register
     67   --  * floats with integral values
     68   local operand = {3, 100, 5.0, -10, -5.0, 10000, -10000}
     69   local operator = {"+", "-", "*", "/", "//", "%", "^",
     70                     "&", "|", "^", "<<", ">>",
     71                     "==", "~=", "<", ">", "<=", ">=",}
     72   for _, op in ipairs(operator) do
     73     local f = assert(load(string.format([[return function (x,y)
     74                 return x %s y
     75               end]], op)))();
     76     for _, o1 in ipairs(operand) do
     77       for _, o2 in ipairs(operand) do
     78         local gab = f(o1, o2)
     79 
     80         _ENV.XX = o1
     81         local code = string.format("return XX %s %s", op, o2)
     82         local res = assert(load(code))()
     83         assert(res == gab)
     84 
     85         _ENV.XX = o2
     86         code = string.format("return (%s) %s XX", o1, op)
     87         res = assert(load(code))()
     88         assert(res == gab)
     89 
     90         code = string.format("return (%s) %s %s", o1, op, o2)
     91         res = assert(load(code))()
     92         assert(res == gab)
     93       end
     94     end
     95   end
     96   _ENV.XX = nil
     97 end
     98 
     99 
    100 -- silly loops
    101 repeat until 1; repeat until true;
    102 while false do end; while nil do end;
    103 
    104 do  -- test old bug (first name could not be an `upvalue')
    105  local a; local function f(x) x={a=1}; x={x=1}; x={G=1} end
    106 end
    107 
    108 
    109 do   -- bug since 5.4.0
    110   -- create code with a table using more than 256 constants
    111   local code = {"local x = {"}
    112   for i = 1, 257 do
    113     code[#code + 1] = i .. ".1,"
    114   end
    115   code[#code + 1] = "};"
    116   code = table.concat(code)
    117 
    118   -- add "ret" to the end of that code and checks that
    119   -- it produces the expected value "val"
    120   local function check (ret, val)
    121     local code = code .. ret
    122     code = load(code)
    123     assert(code() == val)
    124   end
    125 
    126   check("return (1 ~ (2 or 3))", 1 ~ 2)
    127   check("return (1 | (2 or 3))", 1 | 2)
    128   check("return (1 + (2 or 3))", 1 + 2)
    129   check("return (1 << (2 or 3))", 1 << 2)
    130 end
    131 
    132 
    133 local function f (i)
    134   if type(i) ~= 'number' then return i,'jojo'; end;
    135   if i > 0 then return i, f(i-1); end;
    136 end
    137 
    138 x = {f(3), f(5), f(10);};
    139 assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
    140 assert(x[nil] == nil)
    141 x = {f'alo', f'xixi', nil};
    142 assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
    143 x = {f'alo'..'xixi'};
    144 assert(x[1] == 'aloxixi')
    145 x = {f{}}
    146 assert(x[2] == 'jojo' and type(x[1]) == 'table')
    147 
    148 
    149 local f = function (i)
    150   if i < 10 then return 'a';
    151   elseif i < 20 then return 'b';
    152   elseif i < 30 then return 'c';
    153   end;
    154 end
    155 
    156 assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
    157 
    158 for i=1,1000 do break; end;
    159 local n=100;
    160 local i=3;
    161 local t = {};
    162 local a=nil
    163 while not a do
    164   a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
    165 end
    166 assert(a == n*(n+1)/2 and i==3);
    167 assert(t[1] and t[n] and not t[0] and not t[n+1])
    168 
    169 function f(b)
    170   local x = 1;
    171   repeat
    172     local a;
    173     if b==1 then local b=1; x=10; break
    174     elseif b==2 then x=20; break;
    175     elseif b==3 then x=30;
    176     else local a,b,c,d=math.sin(1); x=x+1;
    177     end
    178   until x>=12;
    179   return x;
    180 end;
    181 
    182 assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
    183 
    184 
    185 local f = function (i)
    186   if i < 10 then return 'a'
    187   elseif i < 20 then return 'b'
    188   elseif i < 30 then return 'c'
    189   else return 8
    190   end
    191 end
    192 
    193 assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
    194 
    195 local a, b = nil, 23
    196 x = {f(100)*2+3 or a, a or b+2}
    197 assert(x[1] == 19 and x[2] == 25)
    198 x = {f=2+3 or a, a = b+2}
    199 assert(x.f == 5 and x.a == 25)
    200 
    201 a={y=1}
    202 x = {a.y}
    203 assert(x[1] == 1)
    204 
    205 local function f (i)
    206   while 1 do
    207     if i>0 then i=i-1;
    208     else return; end;
    209   end;
    210 end;
    211 
    212 local function g(i)
    213   while 1 do
    214     if i>0 then i=i-1
    215     else return end
    216   end
    217 end
    218 
    219 f(10); g(10);
    220 
    221 do
    222   function f () return 1,2,3; end
    223   local a, b, c = f();
    224   assert(a==1 and b==2 and c==3)
    225   a, b, c = (f());
    226   assert(a==1 and b==nil and c==nil)
    227 end
    228 
    229 local a,b = 3 and f();
    230 assert(a==1 and b==nil)
    231 
    232 function g() f(); return; end;
    233 assert(g() == nil)
    234 function g() return nil or f() end
    235 a,b = g()
    236 assert(a==1 and b==nil)
    237 
    238 print'+';
    239 
    240 do   -- testing constants
    241   local prog <const> = [[local x <XXX> = 10]]
    242   checkload(prog, "unknown attribute 'XXX'")
    243 
    244   checkload([[local xxx <const> = 20; xxx = 10]],
    245              ":1: attempt to assign to const variable 'xxx'")
    246 
    247   checkload([[
    248     local xx;
    249     local xxx <const> = 20;
    250     local yyy;
    251     local function foo ()
    252       local abc = xx + yyy + xxx;
    253       return function () return function () xxx = yyy end end
    254     end
    255   ]], ":6: attempt to assign to const variable 'xxx'")
    256 
    257   checkload([[
    258     local x <close> = nil
    259     x = io.open()
    260   ]], ":2: attempt to assign to const variable 'x'")
    261 end
    262 
    263 f = [[
    264 return function ( a , b , c , d , e )
    265   local x = a >= b or c or ( d and e ) or nil
    266   return x
    267 end , { a = 1 , b = 2 >= 1 , } or { 1 };
    268 ]]
    269 f = string.gsub(f, "%s+", "\n");   -- force a SETLINE between opcodes
    270 f,a = load(f)();
    271 assert(a.a == 1 and a.b)
    272 
    273 function g (a,b,c,d,e)
    274   if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
    275 end
    276 
    277 local function h (a,b,c,d,e)
    278   while (a>=b or c or (d and e) or nil) do return 1; end;
    279   return 0;
    280 end;
    281 
    282 assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
    283 assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
    284 assert(f(1,2,'a')
    285 ~=          -- force SETLINE before nil
    286 nil, "")
    287 assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
    288 assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
    289                                    h(1,2,nil,1,'x') == 1)
    290 assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
    291                                      h(1,2,nil,nil,'x') == 0)
    292 assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
    293                                    h(1,2,nil,1,nil) == 0)
    294 
    295 assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
    296 x = 2<3 and not 3; assert(x==false)
    297 x = 2<1 or (2>1 and 'a'); assert(x=='a')
    298 
    299 
    300 do
    301   local a; if nil then a=1; else a=2; end;    -- this nil comes as PUSHNIL 2
    302   assert(a==2)
    303 end
    304 
    305 local function F (a)
    306   assert(debug.getinfo(1, "n").name == 'F')
    307   return a,2,3
    308 end
    309 
    310 a,b = F(1)~=nil; assert(a == true and b == nil);
    311 a,b = F(nil)==nil; assert(a == true and b == nil)
    312 
    313 ----------------------------------------------------------------
    314 ------------------------------------------------------------------
    315 
    316 -- sometimes will be 0, sometimes will not...
    317 _ENV.GLOB1 = math.random(0, 1)
    318 
    319 -- basic expressions with their respective values
    320 local basiccases = {
    321   {"nil", nil},
    322   {"false", false},
    323   {"true", true},
    324   {"10", 10},
    325   {"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1},
    326 }
    327 
    328 local prog
    329 
    330 if _ENV.GLOB1 == 0 then
    331   basiccases[2][1] = "F"   -- constant false
    332 
    333   prog = [[
    334     local F <const> = false
    335     if %s then IX = true end
    336     return %s
    337 ]]
    338 else
    339   basiccases[4][1] = "k10"   -- constant 10
    340 
    341   prog = [[
    342     local k10 <const> = 10
    343     if %s then IX = true end
    344     return %s
    345   ]]
    346 end
    347 
    348 print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')')
    349 
    350 
    351 -- operators with their respective values
    352 local binops <const> = {
    353   {" and ", function (a,b) if not a then return a else return b end end},
    354   {" or ", function (a,b) if a then return a else return b end end},
    355 }
    356 
    357 local cases <const> = {}
    358 
    359 -- creates all combinations of '(cases[i] op cases[n-i])' plus
    360 -- 'not(cases[i] op cases[n-i])' (syntax + value)
    361 local function createcases (n)
    362   local res = {}
    363   for i = 1, n - 1 do
    364     for _, v1 in ipairs(cases[i]) do
    365       for _, v2 in ipairs(cases[n - i]) do
    366         for _, op in ipairs(binops) do
    367             local t = {
    368               "(" .. v1[1] .. op[1] .. v2[1] .. ")",
    369               op[2](v1[2], v2[2])
    370             }
    371             res[#res + 1] = t
    372             res[#res + 1] = {"not" .. t[1], not t[2]}
    373         end
    374       end
    375     end
    376   end
    377   return res
    378 end
    379 
    380 -- do not do too many combinations for soft tests
    381 local level = _soft and 3 or 4
    382 
    383 cases[1] = basiccases
    384 for i = 2, level do cases[i] = createcases(i) end
    385 print("+")
    386 
    387 local i = 0
    388 for n = 1, level do
    389   for _, v in pairs(cases[n]) do
    390     local s = v[1]
    391     local p = load(string.format(prog, s, s), "")
    392     IX = false
    393     assert(p() == v[2] and IX == not not v[2])
    394     i = i + 1
    395     if i % 60000 == 0 then print('+') end
    396   end
    397 end
    398 IX = nil
    399 _G.GLOB1 = nil
    400 ------------------------------------------------------------------
    401 
    402 -- testing some syntax errors (chosen through 'gcov')
    403 checkload("for x do", "expected")
    404 checkload("x:call", "expected")
    405 
    406 print'OK'