constructs.lua 9.7 KB

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