[Tarantool-patches] [PATCH luajit 1/3] test: add PUC-Rio Lua 5.1 test suite
Sergey Kaplun
skaplun at tarantool.org
Fri Mar 12 08:36:22 MSK 2021
This patch adds PUC-Rio Lua 5.1 test suite as a part of the LuaJIT
test suite. Source code taken verbatim from
https://www.lua.org/tests/lua5.1-tests.tar.gz.
<lib1.c> and <lib2.c> is slightly modified to be consistent with the
current LuaJIT's LuaC API.
Some tests may fail after this commit. They will be disabled
or adapted in the next patches.
Part of tarantool/tarantool#5845
Part of tarantool/tarantool#4473
---
.luacheckrc | 5 +-
test/CMakeLists.txt | 4 +-
test/PUC-Lua-5.1-tests/CMakeLists.txt | 89 ++
test/PUC-Lua-5.1-tests/README | 41 +
test/PUC-Lua-5.1-tests/all.lua | 137 +++
test/PUC-Lua-5.1-tests/api.lua | 711 +++++++++++++++
test/PUC-Lua-5.1-tests/attrib.lua | 339 ++++++++
test/PUC-Lua-5.1-tests/big.lua | 381 ++++++++
test/PUC-Lua-5.1-tests/calls.lua | 294 +++++++
test/PUC-Lua-5.1-tests/checktable.lua | 77 ++
test/PUC-Lua-5.1-tests/closure.lua | 422 +++++++++
test/PUC-Lua-5.1-tests/code.lua | 143 +++
test/PUC-Lua-5.1-tests/constructs.lua | 240 ++++++
test/PUC-Lua-5.1-tests/db.lua | 499 +++++++++++
test/PUC-Lua-5.1-tests/errors.lua | 250 ++++++
test/PUC-Lua-5.1-tests/etc/ltests.c | 1147 +++++++++++++++++++++++++
test/PUC-Lua-5.1-tests/etc/ltests.h | 92 ++
test/PUC-Lua-5.1-tests/events.lua | 360 ++++++++
test/PUC-Lua-5.1-tests/files.lua | 324 +++++++
test/PUC-Lua-5.1-tests/gc.lua | 312 +++++++
test/PUC-Lua-5.1-tests/libs/lib1.c | 40 +
test/PUC-Lua-5.1-tests/libs/lib11.c | 18 +
test/PUC-Lua-5.1-tests/libs/lib2.c | 28 +
test/PUC-Lua-5.1-tests/libs/lib21.c | 18 +
test/PUC-Lua-5.1-tests/literals.lua | 176 ++++
test/PUC-Lua-5.1-tests/locals.lua | 127 +++
test/PUC-Lua-5.1-tests/main.lua | 159 ++++
test/PUC-Lua-5.1-tests/math.lua | 208 +++++
test/PUC-Lua-5.1-tests/nextvar.lua | 396 +++++++++
test/PUC-Lua-5.1-tests/pm.lua | 273 ++++++
test/PUC-Lua-5.1-tests/sort.lua | 74 ++
test/PUC-Lua-5.1-tests/strings.lua | 176 ++++
test/PUC-Lua-5.1-tests/vararg.lua | 126 +++
test/PUC-Lua-5.1-tests/verybig.lua | 100 +++
34 files changed, 7783 insertions(+), 3 deletions(-)
create mode 100644 test/PUC-Lua-5.1-tests/CMakeLists.txt
create mode 100644 test/PUC-Lua-5.1-tests/README
create mode 100755 test/PUC-Lua-5.1-tests/all.lua
create mode 100644 test/PUC-Lua-5.1-tests/api.lua
create mode 100644 test/PUC-Lua-5.1-tests/attrib.lua
create mode 100644 test/PUC-Lua-5.1-tests/big.lua
create mode 100644 test/PUC-Lua-5.1-tests/calls.lua
create mode 100644 test/PUC-Lua-5.1-tests/checktable.lua
create mode 100644 test/PUC-Lua-5.1-tests/closure.lua
create mode 100644 test/PUC-Lua-5.1-tests/code.lua
create mode 100644 test/PUC-Lua-5.1-tests/constructs.lua
create mode 100644 test/PUC-Lua-5.1-tests/db.lua
create mode 100644 test/PUC-Lua-5.1-tests/errors.lua
create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.c
create mode 100644 test/PUC-Lua-5.1-tests/etc/ltests.h
create mode 100644 test/PUC-Lua-5.1-tests/events.lua
create mode 100644 test/PUC-Lua-5.1-tests/files.lua
create mode 100644 test/PUC-Lua-5.1-tests/gc.lua
create mode 100644 test/PUC-Lua-5.1-tests/libs/lib1.c
create mode 100644 test/PUC-Lua-5.1-tests/libs/lib11.c
create mode 100644 test/PUC-Lua-5.1-tests/libs/lib2.c
create mode 100644 test/PUC-Lua-5.1-tests/libs/lib21.c
create mode 100644 test/PUC-Lua-5.1-tests/literals.lua
create mode 100644 test/PUC-Lua-5.1-tests/locals.lua
create mode 100644 test/PUC-Lua-5.1-tests/main.lua
create mode 100644 test/PUC-Lua-5.1-tests/math.lua
create mode 100644 test/PUC-Lua-5.1-tests/nextvar.lua
create mode 100644 test/PUC-Lua-5.1-tests/pm.lua
create mode 100644 test/PUC-Lua-5.1-tests/sort.lua
create mode 100644 test/PUC-Lua-5.1-tests/strings.lua
create mode 100644 test/PUC-Lua-5.1-tests/vararg.lua
create mode 100644 test/PUC-Lua-5.1-tests/verybig.lua
diff --git a/.luacheckrc b/.luacheckrc
index 1a76108..cbd2912 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -3,10 +3,11 @@ std = 'luajit'
-- This fork also introduces a new global for misc API namespace.
read_globals = { 'misc' }
--- These files are inherited from the vanilla LuaJIT and need to
--- be coherent with the upstream.
+-- These files are inherited from the vanilla LuaJIT or different
+-- test suites and need to be coherent with the upstream.
exclude_files = {
'dynasm/',
'src/',
'test/LuaJIT-tests/',
+ 'test/PUC-Lua-5.1-tests/',
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 99471db..93c43ea 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -43,11 +43,13 @@ endif()
set(LUAJIT_TEST_COMMAND "${LUAJIT_TEST_BINARY} -e dofile[[${LUAJIT_TEST_INIT}]]")
separate_arguments(LUAJIT_TEST_COMMAND)
-add_subdirectory(tarantool-tests)
add_subdirectory(LuaJIT-tests)
+add_subdirectory(PUC-Lua-5.1-tests)
+add_subdirectory(tarantool-tests)
add_custom_target(${PROJECT_NAME}-test DEPENDS
LuaJIT-tests
+ PUC-Lua-5.1-tests
tarantool-tests
)
diff --git a/test/PUC-Lua-5.1-tests/CMakeLists.txt b/test/PUC-Lua-5.1-tests/CMakeLists.txt
new file mode 100644
index 0000000..08bee36
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/CMakeLists.txt
@@ -0,0 +1,89 @@
+# Test suite that has been added from PUC-Rio Lua 5.1 test archive
+# in scope of https://github.com/tarantool/tarantool/issues/4473.
+
+# See the rationale in the root CMakeLists.txt.
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+set(TEST_RUNNER ${CMAKE_CURRENT_SOURCE_DIR}/all.lua)
+set(LIB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/libs)
+set(TESTLIB_PATH ${CMAKE_CURRENT_BINARY_DIR}/libs)
+
+# XXX: -fPIC is required to linking with static library.
+if(NOT BUILDMODE STREQUAL "static")
+ # Build additional C libraries for tests.
+ macro(build_lib lib sources)
+ add_library(${lib} SHARED EXCLUDE_FROM_ALL ${sources})
+ target_include_directories(${lib} PRIVATE
+ ${LUAJIT_SOURCE_DIR}
+ )
+ set_target_properties(${lib} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${TESTLIB_PATH}"
+ PREFIX ""
+ )
+ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set_target_properties(${lib} PROPERTIES
+ LINK_FLAGS "-undefined dynamic_lookup"
+ )
+ endif()
+ target_link_libraries(${lib} PRIVATE libluajit_shared)
+ list(APPEND TESTLIBS ${lib})
+ endmacro()
+
+ build_lib(lib1 ${LIB_SOURCES}/lib1.c)
+ build_lib(lib11 ${LIB_SOURCES}/lib1.c ${LIB_SOURCES}/lib11.c)
+ build_lib(lib2 ${LIB_SOURCES}/lib2.c)
+ build_lib(lib21 ${LIB_SOURCES}/lib2.c ${LIB_SOURCES}/lib21.c)
+
+ set(LIB2COPY "${TESTLIB_PATH}/lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(LIB_COPY "${TESTLIB_PATH}/-lib2${CMAKE_SHARED_LIBRARY_SUFFIX}")
+
+ add_custom_command(
+ COMMENT "Copping lib2 to -lib2 for PUC-Rio Lua 5.1 tests"
+ OUTPUT ${LIB_COPY}
+ DEPENDS ${TESTLIBS}
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIB2COPY} ${LIB_COPY}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ list(APPEND TESTLIBS ${LIB_COPY})
+endif()
+
+set(CUSTOM_TEST_DIR ${TESTLIB_PATH}/P1)
+add_custom_command(
+ COMMENT "Create directory for PUC-Rio Lua 5.1 tests"
+ OUTPUT ${CUSTOM_TEST_DIR}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CUSTOM_TEST_DIR}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(LUA_PATH "?\;${CMAKE_CURRENT_SOURCE_DIR}/?.lua")
+
+# TODO: PUC-Rio Lua 5.1 test suite also has special header
+# <ltests.h> and <ltests.c> translation unit to check some
+# internal behaviour of the Lua implementation (see etc/
+# directory). It modifies realloc function to check memory
+# consistency and also contains tests for yield in hooks
+# and for the Lua C API.
+# But, unfortunately, <ltests.c> depends on specific PUC-Rio Lua 5.1
+# internal headers and should be adopted for LuaJIT.
+
+add_custom_target(PUC-Lua-5.1-tests
+ DEPENDS ${LUAJIT_TEST_BINARY} ${TESTLIBS} ${CUSTOM_TEST_DIR}
+)
+
+add_custom_command(TARGET PUC-Lua-5.1-tests
+ COMMENT "Running PUC-Rio Lua 5.1 tests"
+ COMMAND
+ env
+ # Tarantool doesn't support LUA_INIT and most likely it
+ # never will.
+ # See https://github.com/tarantool/tarantool/issues/5744
+ # for more info.
+ # LUA_PATH="${CMAKE_CURRENT_BINARY_DIR}/?.lua\;\;"
+ # LUA_INIT="package.path='?\;'..package.path"
+ # So use less preferable way for tests.
+ LUA_PATH="${LUA_PATH}\;\;"
+ ${LUAJIT_TEST_COMMAND} ${TEST_RUNNER}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+# vim: expandtab tabstop=2 shiftwidth=2
diff --git a/test/PUC-Lua-5.1-tests/README b/test/PUC-Lua-5.1-tests/README
new file mode 100644
index 0000000..e2d4b28
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/README
@@ -0,0 +1,41 @@
+This tarball contains the official test scripts for Lua 5.1.
+Unlike Lua itself, these tests do not aim portability, small footprint,
+or easy of use. (Their main goal is to try to crash Lua.) They are not
+intended for general use. You are wellcome to use them, but expect to
+have to "dirt your hands".
+
+The tarball should expand in the following contents:
+ - several .lua scripts with the tests
+ - a main "all.lua" Lua script that invokes all the other scripts
+ - a subdirectory "libs" with an empty subdirectory "libs/P1",
+ to be used by the scripts
+ - a subdirectory "etc" with some extra files
+
+To run the tests, do as follows:
+
+- go to the test directory
+
+- set LUA_PATH to "?;./?.lua" (or, better yet, set LUA_PATH to "./?.lua;;"
+ and LUA_INIT to "package.path = '?;'..package.path")
+
+- run "lua all.lua"
+
+
+--------------------------------------------
+Internal tests
+--------------------------------------------
+
+Some tests need a special library, "testC", that gives access to
+several internal structures in Lua.
+This library is only available when Lua is compiled in debug mode.
+The scripts automatically detect its absence and skip those tests.
+
+If you want to run these tests, move etc/ltests.c and etc/ltests.h to
+the directory with the source Lua files, and recompile Lua with
+the option -DLUA_USER_H='"ltests.h"' (or its equivalent to define
+LUA_USER_H as the string "ltests.h", including the quotes). This
+option not only adds the testC library, but it adds several other
+internal tests as well. After the recompilation, run the tests
+as before.
+
+
diff --git a/test/PUC-Lua-5.1-tests/all.lua b/test/PUC-Lua-5.1-tests/all.lua
new file mode 100755
index 0000000..8c4afac
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/all.lua
@@ -0,0 +1,137 @@
+#!../lua
+
+math.randomseed(0)
+
+collectgarbage("setstepmul", 180)
+collectgarbage("setpause", 190)
+
+
+--[=[
+ example of a long [comment],
+ [[spanning several [lines]]]
+
+]=]
+
+print("current path:\n " .. string.gsub(package.path, ";", "\n "))
+
+
+local msgs = {}
+function Message (m)
+ print(m)
+ msgs[#msgs+1] = string.sub(m, 3, -3)
+end
+
+
+local c = os.clock()
+
+assert(os.setlocale"C")
+
+local T,print,gcinfo,format,write,assert,type =
+ T,print,gcinfo,string.format,io.write,assert,type
+
+local function formatmem (m)
+ if m < 1024 then return m
+ else
+ m = m/1024 - m/1024%1
+ if m < 1024 then return m.."K"
+ else
+ m = m/1024 - m/1024%1
+ return m.."M"
+ end
+ end
+end
+
+local showmem = function ()
+ if not T then
+ print(format(" ---- total memory: %s ----\n", formatmem(gcinfo())))
+ else
+ T.checkmemory()
+ local a,b,c = T.totalmem()
+ local d,e = gcinfo()
+ print(format(
+ "\n ---- total memory: %s (%dK), max use: %s, blocks: %d\n",
+ formatmem(a), d, formatmem(c), b))
+ end
+end
+
+
+--
+-- redefine dofile to run files through dump/undump
+--
+dofile = function (n)
+ showmem()
+ local f = assert(loadfile(n))
+ local b = string.dump(f)
+ f = assert(loadstring(b))
+ return f()
+end
+
+dofile('main.lua')
+
+do
+ local u = newproxy(true)
+ local newproxy, stderr = newproxy, io.stderr
+ getmetatable(u).__gc = function (o)
+ stderr:write'.'
+ newproxy(o)
+ end
+end
+
+local f = assert(loadfile('gc.lua'))
+f()
+dofile('db.lua')
+assert(dofile('calls.lua') == deep and deep)
+dofile('strings.lua')
+dofile('literals.lua')
+assert(dofile('attrib.lua') == 27)
+assert(dofile('locals.lua') == 5)
+dofile('constructs.lua')
+dofile('code.lua')
+do
+ local f = coroutine.wrap(assert(loadfile('big.lua')))
+ assert(f() == 'b')
+ assert(f() == 'a')
+end
+dofile('nextvar.lua')
+dofile('pm.lua')
+dofile('api.lua')
+assert(dofile('events.lua') == 12)
+dofile('vararg.lua')
+dofile('closure.lua')
+dofile('errors.lua')
+dofile('math.lua')
+dofile('sort.lua')
+assert(dofile('verybig.lua') == 10); collectgarbage()
+dofile('files.lua')
+
+if #msgs > 0 then
+ print("\ntests not performed:")
+ for i=1,#msgs do
+ print(msgs[i])
+ end
+ print()
+end
+
+print("final OK !!!")
+print('cleaning all!!!!')
+
+debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
+
+local _G, collectgarbage, showmem, print, format, clock =
+ _G, collectgarbage, showmem, print, format, os.clock
+
+local a={}
+for n in pairs(_G) do a[n] = 1 end
+a.tostring = nil
+a.___Glob = nil
+for n in pairs(a) do _G[n] = nil end
+
+a = nil
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage()
+collectgarbage();showmem()
+
+print(format("\n\ntotal time: %.2f\n", clock()-c))
diff --git a/test/PUC-Lua-5.1-tests/api.lua b/test/PUC-Lua-5.1-tests/api.lua
new file mode 100644
index 0000000..c955ebf
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/api.lua
@@ -0,0 +1,711 @@
+
+if T==nil then
+ (Message or print)('\a\n >>> testC not active: skipping API tests <<<\n\a')
+ return
+end
+
+
+
+function tcheck (t1, t2)
+ table.remove(t1, 1) -- remove code
+ assert(table.getn(t1) == table.getn(t2))
+ for i=1,table.getn(t1) do assert(t1[i] == t2[i]) end
+end
+
+function pack(...) return arg end
+
+
+print('testing C API')
+
+-- testing allignment
+a = T.d2s(12458954321123)
+assert(string.len(a) == 8) -- sizeof(double)
+assert(T.s2d(a) == 12458954321123)
+
+a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
+assert(a == 2 and b == 3 and not c)
+
+-- test that all trues are equal
+a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
+assert(a == b and a == true and c == false)
+a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\
+ tobool -3; tobool -3; tobool -3; return 3"
+assert(a==0 and b==1 and c==0)
+
+
+a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
+assert(a == 40 and b == 5 and not c)
+
+t = pack(T.testC("settop 5; gettop; return .", 2, 3))
+tcheck(t, {n=4,2,3})
+
+t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
+assert(t.n == 10 and t[1] == nil and t[10] == nil)
+
+t = pack(T.testC("remove -2; gettop; return .", 2, 3, 4))
+tcheck(t, {n=2,2,4})
+
+t = pack(T.testC("insert -1; gettop; return .", 2, 3))
+tcheck(t, {n=2,2,3})
+
+t = pack(T.testC("insert 3; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=4,2,5,3,4})
+
+t = pack(T.testC("replace 2; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,5,3,4})
+
+t = pack(T.testC("replace -2; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,2,3,5})
+
+t = pack(T.testC("remove 3; gettop; return .", 2, 3, 4, 5))
+tcheck(t, {n=3,2,4,5})
+
+t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
+ insert 2; pushvalue 1; remove 1; insert 1; \
+ insert -2; pushvalue -2; remove -3; gettop; return .",
+ 2, 3, 4, 5, 10, 40, 90))
+tcheck(t, {n=7,2,3,4,5,10,40,90})
+
+t = pack(T.testC("concat 5; gettop; return .", "alo", 2, 3, "joao", 12))
+tcheck(t, {n=1,"alo23joao12"})
+
+-- testing MULTRET
+t = pack(T.testC("rawcall 2,-1; gettop; return .",
+ function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
+tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
+
+do -- test returning more results than fit in the caller stack
+ local a = {}
+ for i=1,1000 do a[i] = true end; a[999] = 10
+ local b = T.testC([[call 1 -1; pop 1; tostring -1; return 1]], unpack, a)
+ assert(b == "10")
+end
+
+
+-- testing lessthan
+assert(T.testC("lessthan 2 5, return 1", 3, 2, 2, 4, 2, 2))
+assert(T.testC("lessthan 5 2, return 1", 4, 2, 2, 3, 2, 2))
+assert(not T.testC("lessthan 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
+assert(not T.testC("lessthan -3 2, return 1", "3", "2", "2", "4", "2", "2"))
+
+local b = {__lt = function (a,b) return a[1] < b[1] end}
+local a1,a3,a4 = setmetatable({1}, b),
+ setmetatable({3}, b),
+ setmetatable({4}, b)
+assert(T.testC("lessthan 2 5, return 1", a3, 2, 2, a4, 2, 2))
+assert(T.testC("lessthan 5 -6, return 1", a4, 2, 2, a3, 2, 2))
+a,b = T.testC("lessthan 5 -6, return 2", a1, 2, 2, a3, 2, 20)
+assert(a == 20 and b == false)
+
+
+-- testing lua_is
+
+function count (x, n)
+ n = n or 2
+ local prog = [[
+ isnumber %d;
+ isstring %d;
+ isfunction %d;
+ iscfunction %d;
+ istable %d;
+ isuserdata %d;
+ isnil %d;
+ isnull %d;
+ return 8
+ ]]
+ prog = string.format(prog, n, n, n, n, n, n, n, n)
+ local a,b,c,d,e,f,g,h = T.testC(prog, x)
+ return a+b+c+d+e+f+g+(100*h)
+end
+
+assert(count(3) == 2)
+assert(count('alo') == 1)
+assert(count('32') == 2)
+assert(count({}) == 1)
+assert(count(print) == 2)
+assert(count(function () end) == 1)
+assert(count(nil) == 1)
+assert(count(io.stdin) == 1)
+assert(count(nil, 15) == 100)
+
+-- testing lua_to...
+
+function to (s, x, n)
+ n = n or 2
+ return T.testC(string.format("%s %d; return 1", s, n), x)
+end
+
+assert(to("tostring", {}) == nil)
+assert(to("tostring", "alo") == "alo")
+assert(to("tostring", 12) == "12")
+assert(to("tostring", 12, 3) == nil)
+assert(to("objsize", {}) == 0)
+assert(to("objsize", "alo\0\0a") == 6)
+assert(to("objsize", T.newuserdata(0)) == 0)
+assert(to("objsize", T.newuserdata(101)) == 101)
+assert(to("objsize", 12) == 2)
+assert(to("objsize", 12, 3) == 0)
+assert(to("tonumber", {}) == 0)
+assert(to("tonumber", "12") == 12)
+assert(to("tonumber", "s2") == 0)
+assert(to("tonumber", 1, 20) == 0)
+a = to("tocfunction", math.deg)
+assert(a(3) == math.deg(3) and a ~= math.deg)
+
+
+-- testing errors
+
+a = T.testC([[
+ loadstring 2; call 0,1;
+ pushvalue 3; insert -2; call 1, 1;
+ call 0, 0;
+ return 1
+]], "x=150", function (a) assert(a==nil); return 3 end)
+
+assert(type(a) == 'string' and x == 150)
+
+function check3(p, ...)
+ assert(arg.n == 3)
+ assert(string.find(arg[3], p))
+end
+check3(":1:", T.testC("loadstring 2; gettop; return .", "x="))
+check3("cannot read", T.testC("loadfile 2; gettop; return .", "."))
+check3("cannot open xxxx", T.testC("loadfile 2; gettop; return .", "xxxx"))
+
+-- testing table access
+
+a = {x=0, y=12}
+x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
+ a, 3, "y", 4, "x")
+assert(x == 0 and y == 12)
+T.testC("settable -5", a, 3, 4, "x", 15)
+assert(a.x == 15)
+a[a] = print
+x = T.testC("gettable 2; return 1", a) -- table and key are the same object!
+assert(x == print)
+T.testC("settable 2", a, "x") -- table and key are the same object!
+assert(a[a] == "x")
+
+b = setmetatable({p = a}, {})
+getmetatable(b).__index = function (t, i) return t.p[i] end
+k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
+assert(x == 15 and k == 35)
+getmetatable(b).__index = function (t, i) return a[i] end
+getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
+y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
+assert(y == 12)
+k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
+assert(a.x == 16 and k == 4)
+a[b] = 'xuxu'
+y = T.testC("gettable 2, return 1", b)
+assert(y == 'xuxu')
+T.testC("settable 2", b, 19)
+assert(a[b] == 19)
+
+-- testing next
+a = {}
+t = pack(T.testC("next; gettop; return .", a, nil))
+tcheck(t, {n=1,a})
+a = {a=3}
+t = pack(T.testC("next; gettop; return .", a, nil))
+tcheck(t, {n=3,a,'a',3})
+t = pack(T.testC("next; pop 1; next; gettop; return .", a, nil))
+tcheck(t, {n=1,a})
+
+
+
+-- testing upvalues
+
+do
+ local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
+ t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
+ assert(b == 10 and c == 20 and type(t) == 'table')
+ a, b = A([[tostring U3; tonumber U4; return 2]])
+ assert(a == nil and b == 0)
+ A([[pushnum 100; pushnum 200; replace U2; replace U1]])
+ b, c = A([[pushvalue U1; pushvalue U2; return 2]])
+ assert(b == 100 and c == 200)
+ A([[replace U2; replace U1]], {x=1}, {x=2})
+ b, c = A([[pushvalue U1; pushvalue U2; return 2]])
+ assert(b.x == 1 and c.x == 2)
+ T.checkmemory()
+end
+
+local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
+assert(T.upvalue(f, 1) == 10 and
+ T.upvalue(f, 2) == 20 and
+ T.upvalue(f, 3) == nil)
+T.upvalue(f, 2, "xuxu")
+assert(T.upvalue(f, 2) == "xuxu")
+
+
+-- testing environments
+
+assert(T.testC"pushvalue G; return 1" == _G)
+assert(T.testC"pushvalue E; return 1" == _G)
+local a = {}
+T.testC("replace E; return 1", a)
+assert(T.testC"pushvalue G; return 1" == _G)
+assert(T.testC"pushvalue E; return 1" == a)
+assert(debug.getfenv(T.testC) == a)
+assert(debug.getfenv(T.upvalue) == _G)
+-- userdata inherit environment
+local u = T.testC"newuserdata 0; return 1"
+assert(debug.getfenv(u) == a)
+-- functions inherit environment
+u = T.testC"pushcclosure 0; return 1"
+assert(debug.getfenv(u) == a)
+debug.setfenv(T.testC, _G)
+assert(T.testC"pushvalue E; return 1" == _G)
+
+local b = newproxy()
+assert(debug.getfenv(b) == _G)
+assert(debug.setfenv(b, a))
+assert(debug.getfenv(b) == a)
+
+
+
+-- testing locks (refs)
+
+-- reuse of references
+local i = T.ref{}
+T.unref(i)
+assert(T.ref{} == i)
+
+Arr = {}
+Lim = 100
+for i=1,Lim do -- lock many objects
+ Arr[i] = T.ref({})
+end
+
+assert(T.ref(nil) == -1 and T.getref(-1) == nil)
+T.unref(-1); T.unref(-1)
+
+for i=1,Lim do -- unlock all them
+ T.unref(Arr[i])
+end
+
+function printlocks ()
+ local n = T.testC("gettable R; return 1", "n")
+ print("n", n)
+ for i=0,n do
+ print(i, T.testC("gettable R; return 1", i))
+ end
+end
+
+
+for i=1,Lim do -- lock many objects
+ Arr[i] = T.ref({})
+end
+
+for i=1,Lim,2 do -- unlock half of them
+ T.unref(Arr[i])
+end
+
+assert(type(T.getref(Arr[2])) == 'table')
+
+
+assert(T.getref(-1) == nil)
+
+
+a = T.ref({})
+
+collectgarbage()
+
+assert(type(T.getref(a)) == 'table')
+
+
+-- colect in cl the `val' of all collected userdata
+tt = {}
+cl = {n=0}
+A = nil; B = nil
+local F
+F = function (x)
+ local udval = T.udataval(x)
+ table.insert(cl, udval)
+ local d = T.newuserdata(100) -- cria lixo
+ d = nil
+ assert(debug.getmetatable(x).__gc == F)
+ loadstring("table.insert({}, {})")() -- cria mais lixo
+ collectgarbage() -- forca coleta de lixo durante coleta!
+ assert(debug.getmetatable(x).__gc == F) -- coleta anterior nao melou isso?
+ local dummy = {} -- cria lixo durante coleta
+ if A ~= nil then
+ assert(type(A) == "userdata")
+ assert(T.udataval(A) == B)
+ debug.getmetatable(A) -- just acess it
+ end
+ A = x -- ressucita userdata
+ B = udval
+ return 1,2,3
+end
+tt.__gc = F
+
+-- test whether udate collection frees memory in the right time
+do
+ collectgarbage();
+ collectgarbage();
+ local x = collectgarbage("count");
+ local a = T.newuserdata(5001)
+ assert(T.testC("objsize 2; return 1", a) == 5001)
+ assert(collectgarbage("count") >= x+4)
+ a = nil
+ collectgarbage();
+ assert(collectgarbage("count") <= x+1)
+ -- udata without finalizer
+ x = collectgarbage("count")
+ collectgarbage("stop")
+ for i=1,1000 do newproxy(false) end
+ assert(collectgarbage("count") > x+10)
+ collectgarbage()
+ assert(collectgarbage("count") <= x+1)
+ -- udata with finalizer
+ x = collectgarbage("count")
+ collectgarbage()
+ collectgarbage("stop")
+ a = newproxy(true)
+ getmetatable(a).__gc = function () end
+ for i=1,1000 do newproxy(a) end
+ assert(collectgarbage("count") >= x+10)
+ collectgarbage() -- this collection only calls TM, without freeing memory
+ assert(collectgarbage("count") >= x+10)
+ collectgarbage() -- now frees memory
+ assert(collectgarbage("count") <= x+1)
+end
+
+
+collectgarbage("stop")
+
+-- create 3 userdatas with tag `tt'
+a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
+b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
+c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
+
+-- create userdata without meta table
+x = T.newuserdata(4)
+y = T.newuserdata(0)
+
+assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
+
+d=T.ref(a);
+e=T.ref(b);
+f=T.ref(c);
+t = {T.getref(d), T.getref(e), T.getref(f)}
+assert(t[1] == a and t[2] == b and t[3] == c)
+
+t=nil; a=nil; c=nil;
+T.unref(e); T.unref(f)
+
+collectgarbage()
+
+-- check that unref objects have been collected
+assert(table.getn(cl) == 1 and cl[1] == nc)
+
+x = T.getref(d)
+assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
+x =nil
+tt.b = b -- create cycle
+tt=nil -- frees tt for GC
+A = nil
+b = nil
+T.unref(d);
+n5 = T.newuserdata(0)
+debug.setmetatable(n5, {__gc=F})
+n5 = T.udataval(n5)
+collectgarbage()
+assert(table.getn(cl) == 4)
+-- check order of collection
+assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
+
+
+a, na = {}, {}
+for i=30,1,-1 do
+ a[i] = T.newuserdata(0)
+ debug.setmetatable(a[i], {__gc=F})
+ na[i] = T.udataval(a[i])
+end
+cl = {}
+a = nil; collectgarbage()
+assert(table.getn(cl) == 30)
+for i=1,30 do assert(cl[i] == na[i]) end
+na = nil
+
+
+for i=2,Lim,2 do -- unlock the other half
+ T.unref(Arr[i])
+end
+
+x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
+assert(T.testC("objsize 2; return 1", x) == 41)
+cl = {}
+a = {[x] = 1}
+x = T.udataval(x)
+collectgarbage()
+-- old `x' cannot be collected (`a' still uses it)
+assert(table.getn(cl) == 0)
+for n in pairs(a) do a[n] = nil end
+collectgarbage()
+assert(table.getn(cl) == 1 and cl[1] == x) -- old `x' must be collected
+
+-- testing lua_equal
+assert(T.testC("equal 2 4; return 1", print, 1, print, 20))
+assert(T.testC("equal 3 2; return 1", 'alo', "alo"))
+assert(T.testC("equal 2 3; return 1", nil, nil))
+assert(not T.testC("equal 2 3; return 1", {}, {}))
+assert(not T.testC("equal 2 3; return 1"))
+assert(not T.testC("equal 2 3; return 1", 3))
+
+-- testing lua_equal with fallbacks
+do
+ local map = {}
+ local t = {__eq = function (a,b) return map[a] == map[b] end}
+ local function f(x)
+ local u = T.newuserdata(0)
+ debug.setmetatable(u, t)
+ map[u] = x
+ return u
+ end
+ assert(f(10) == f(10))
+ assert(f(10) ~= f(11))
+ assert(T.testC("equal 2 3; return 1", f(10), f(10)))
+ assert(not T.testC("equal 2 3; return 1", f(10), f(20)))
+ t.__eq = nil
+ assert(f(10) ~= f(10))
+end
+
+print'+'
+
+
+
+-------------------------------------------------------------------------
+do -- testing errors during GC
+ local a = {}
+ for i=1,20 do
+ a[i] = T.newuserdata(i) -- creates several udata
+ end
+ for i=1,20,2 do -- mark half of them to raise error during GC
+ debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
+ end
+ for i=2,20,2 do -- mark the other half to count and to create more garbage
+ debug.setmetatable(a[i], {__gc = function (x) loadstring("A=A+1")() end})
+ end
+ _G.A = 0
+ a = 0
+ while 1 do
+ if xpcall(collectgarbage, function (s) a=a+1 end) then
+ break -- stop if no more errors
+ end
+ end
+ assert(a == 10) -- number of errors
+ assert(A == 10) -- number of normal collections
+end
+-------------------------------------------------------------------------
+-- test for userdata vals
+do
+ local a = {}; local lim = 30
+ for i=0,lim do a[i] = T.pushuserdata(i) end
+ for i=0,lim do assert(T.udataval(a[i]) == i) end
+ for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
+ for i=0,lim do a[a[i]] = i end
+ for i=0,lim do a[T.pushuserdata(i)] = i end
+ assert(type(tostring(a[1])) == "string")
+end
+
+
+-------------------------------------------------------------------------
+-- testing multiple states
+T.closestate(T.newstate());
+L1 = T.newstate()
+assert(L1)
+assert(pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")).n == 0)
+
+a, b = T.doremote(L1, "return f()")
+assert(a == 'alo' and b == '3')
+
+T.doremote(L1, "_ERRORMESSAGE = nil")
+-- error: `sin' is not defined
+a, b = T.doremote(L1, "return sin(1)")
+assert(a == nil and b == 2) -- 2 == run-time error
+
+-- error: syntax error
+a, b, c = T.doremote(L1, "return a+")
+assert(a == nil and b == 3 and type(c) == "string") -- 3 == syntax error
+
+T.loadlib(L1)
+a, b = T.doremote(L1, [[
+ a = strlibopen()
+ a = packageopen()
+ a = baselibopen(); assert(a == _G and require("_G") == a)
+ a = iolibopen(); assert(type(a.read) == "function")
+ assert(require("io") == a)
+ a = tablibopen(); assert(type(a.insert) == "function")
+ a = dblibopen(); assert(type(a.getlocal) == "function")
+ a = mathlibopen(); assert(type(a.sin) == "function")
+ return string.sub('okinama', 1, 2)
+]])
+assert(a == "ok")
+
+T.closestate(L1);
+
+L1 = T.newstate()
+T.loadlib(L1)
+T.doremote(L1, "a = {}")
+T.testC(L1, [[pushstring a; gettable G; pushstring x; pushnum 1;
+ settable -3]])
+assert(T.doremote(L1, "return a.x") == "1")
+
+T.closestate(L1)
+
+L1 = nil
+
+print('+')
+
+-------------------------------------------------------------------------
+-- testing memory limits
+-------------------------------------------------------------------------
+collectgarbage()
+T.totalmem(T.totalmem()+5000) -- set low memory limit (+5k)
+assert(not pcall(loadstring"local a={}; for i=1,100000 do a[i]=i end"))
+T.totalmem(1000000000) -- restore high limit
+
+
+local function stack(x) if x>0 then stack(x-1) end end
+
+-- test memory errors; increase memory limit in small steps, so that
+-- we get memory errors in different parts of a given task, up to there
+-- is enough memory to complete the task without errors
+function testamem (s, f)
+ collectgarbage()
+ stack(10) -- ensure minimum stack size
+ local M = T.totalmem()
+ local oldM = M
+ local a,b = nil
+ while 1 do
+ M = M+3 -- increase memory limit in small steps
+ T.totalmem(M)
+ a, b = pcall(f)
+ if a and b then break end -- stop when no more errors
+ collectgarbage()
+ if not a and not string.find(b, "memory") then -- `real' error?
+ T.totalmem(1000000000) -- restore high limit
+ error(b, 0)
+ end
+ end
+ T.totalmem(1000000000) -- restore high limit
+ print("\nlimit for " .. s .. ": " .. M-oldM)
+ return b
+end
+
+
+-- testing memory errors when creating a new state
+
+b = testamem("state creation", T.newstate)
+T.closestate(b); -- close new state
+
+
+-- testing threads
+
+function expand (n,s)
+ if n==0 then return "" end
+ local e = string.rep("=", n)
+ return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
+ e, s, expand(n-1,s), e)
+end
+
+G=0; collectgarbage(); a =collectgarbage("count")
+loadstring(expand(20,"G=G+1"))()
+assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
+
+testamem("thread creation", function ()
+ return T.doonnewstack("x=1") == 0 -- try to create thread
+end)
+
+
+-- testing memory x compiler
+
+testamem("loadstring", function ()
+ return loadstring("x=1") -- try to do a loadstring
+end)
+
+
+local testprog = [[
+local function foo () return end
+local t = {"x"}
+a = "aaa"
+for _, v in ipairs(t) do a=a..v end
+return true
+]]
+
+-- testing memory x dofile
+_G.a = nil
+local t =os.tmpname()
+local f = assert(io.open(t, "w"))
+f:write(testprog)
+f:close()
+testamem("dofile", function ()
+ local a = loadfile(t)
+ return a and a()
+end)
+assert(os.remove(t))
+assert(_G.a == "aaax")
+
+
+-- other generic tests
+
+testamem("string creation", function ()
+ local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
+ return (a == 'ablo ablo')
+end)
+
+testamem("dump/undump", function ()
+ local a = loadstring(testprog)
+ local b = a and string.dump(a)
+ a = b and loadstring(b)
+ return a and a()
+end)
+
+local t = os.tmpname()
+testamem("file creation", function ()
+ local f = assert(io.open(t, 'w'))
+ assert (not io.open"nomenaoexistente")
+ io.close(f);
+ return not loadfile'nomenaoexistente'
+end)
+assert(os.remove(t))
+
+testamem("table creation", function ()
+ local a, lim = {}, 10
+ for i=1,lim do a[i] = i; a[i..'a'] = {} end
+ return (type(a[lim..'a']) == 'table' and a[lim] == lim)
+end)
+
+local a = 1
+close = nil
+testamem("closure creation", function ()
+ function close (b,c)
+ return function (x) return a+b+c+x end
+ end
+ return (close(2,3)(4) == 10)
+end)
+
+testamem("coroutines", function ()
+ local a = coroutine.wrap(function ()
+ coroutine.yield(string.rep("a", 10))
+ return {}
+ end)
+ assert(string.len(a()) == 10)
+ return a()
+end)
+
+print'+'
+
+-- testing some auxlib functions
+assert(T.gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
+assert(T.gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
+assert(T.gsub("", "alo", "//") == "")
+assert(T.gsub("...", ".", "/.") == "/././.")
+assert(T.gsub("...", "...", "") == "")
+
+
+print'OK'
+
diff --git a/test/PUC-Lua-5.1-tests/attrib.lua b/test/PUC-Lua-5.1-tests/attrib.lua
new file mode 100644
index 0000000..655669b
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/attrib.lua
@@ -0,0 +1,339 @@
+do --[
+
+print "testing require"
+
+assert(require"string" == string)
+assert(require"math" == math)
+assert(require"table" == table)
+assert(require"io" == io)
+assert(require"os" == os)
+assert(require"debug" == debug)
+assert(require"coroutine" == coroutine)
+
+assert(type(package.path) == "string")
+assert(type(package.cpath) == "string")
+assert(type(package.loaded) == "table")
+assert(type(package.preload) == "table")
+
+
+local DIR = "libs/"
+
+local function createfiles (files, preextras, posextras)
+ for n,c in pairs(files) do
+ io.output(DIR..n)
+ io.write(string.format(preextras, n))
+ io.write(c)
+ io.write(string.format(posextras, n))
+ io.close(io.output())
+ end
+end
+
+function removefiles (files)
+ for n in pairs(files) do
+ os.remove(DIR..n)
+ end
+end
+
+local files = {
+ ["A.lua"] = "",
+ ["B.lua"] = "assert(...=='B');require 'A'",
+ ["A.lc"] = "",
+ ["A"] = "",
+ ["L"] = "",
+ ["XXxX"] = "",
+ ["C.lua"] = "package.loaded[...] = 25; require'C'"
+}
+
+AA = nil
+local extras = [[
+NAME = '%s'
+REQUIRED = ...
+return AA]]
+
+createfiles(files, "", extras)
+
+
+local oldpath = package.path
+
+package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
+
+local try = function (p, n, r)
+ NAME = nil
+ local rr = require(p)
+ assert(NAME == n)
+ assert(REQUIRED == p)
+ assert(rr == r)
+end
+
+assert(require"C" == 25)
+assert(require"C" == 25)
+AA = nil
+try('B', 'B.lua', true)
+assert(package.loaded.B)
+assert(require"B" == true)
+assert(package.loaded.A)
+package.loaded.A = nil
+try('B', nil, true) -- should not reload package
+try('A', 'A.lua', true)
+package.loaded.A = nil
+os.remove(DIR..'A.lua')
+AA = {}
+try('A', 'A.lc', AA) -- now must find second option
+assert(require("A") == AA)
+AA = false
+try('K', 'L', false) -- default option
+try('K', 'L', false) -- default option (should reload it)
+assert(rawget(_G, "_REQUIREDNAME") == nil)
+
+AA = "x"
+try("X", "XXxX", AA)
+
+
+removefiles(files)
+
+
+-- testing require of sub-packages
+
+package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
+
+files = {
+ ["P1/init.lua"] = "AA = 10",
+ ["P1/xuxu.lua"] = "AA = 20",
+}
+
+createfiles(files, "module(..., package.seeall)\n", "")
+AA = 0
+
+local m = assert(require"P1")
+assert(m == P1 and m._NAME == "P1" and AA == 0 and m.AA == 10)
+assert(require"P1" == P1 and P1 == m)
+assert(require"P1" == P1)
+assert(P1._PACKAGE == "")
+
+local m = assert(require"P1.xuxu")
+assert(m == P1.xuxu and m._NAME == "P1.xuxu" and AA == 0 and m.AA == 20)
+assert(require"P1.xuxu" == P1.xuxu and P1.xuxu == m)
+assert(require"P1.xuxu" == P1.xuxu)
+assert(require"P1" == P1)
+assert(P1.xuxu._PACKAGE == "P1.")
+assert(P1.AA == 10 and P1._PACKAGE == "")
+assert(P1._G == _G and P1.xuxu._G == _G)
+
+
+
+removefiles(files)
+
+
+package.path = ""
+assert(not pcall(require, "file_does_not_exist"))
+package.path = "??\0?"
+assert(not pcall(require, "file_does_not_exist1"))
+
+package.path = oldpath
+
+-- check 'require' error message
+local fname = "file_does_not_exist2"
+local m, err = pcall(require, fname)
+for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
+ t = string.gsub(t, "?", fname)
+ assert(string.find(err, t, 1, true))
+end
+
+
+local function import(...)
+ local f = {...}
+ return function (m)
+ for i=1, #f do m[f[i]] = _G[f[i]] end
+ end
+end
+
+local assert, module, package = assert, module, package
+X = nil; x = 0; assert(_G.x == 0) -- `x' must be a global variable
+module"X"; x = 1; assert(_M.x == 1)
+module"X.a.b.c"; x = 2; assert(_M.x == 2)
+module("X.a.b", package.seeall); x = 3
+assert(X._NAME == "X" and X.a.b.c._NAME == "X.a.b.c" and X.a.b._NAME == "X.a.b")
+assert(X._M == X and X.a.b.c._M == X.a.b.c and X.a.b._M == X.a.b)
+assert(X.x == 1 and X.a.b.c.x == 2 and X.a.b.x == 3)
+assert(X._PACKAGE == "" and X.a.b.c._PACKAGE == "X.a.b." and
+ X.a.b._PACKAGE == "X.a.")
+assert(_PACKAGE.."c" == "X.a.c")
+assert(X.a._NAME == nil and X.a._M == nil)
+module("X.a", import("X")) ; x = 4
+assert(X.a._NAME == "X.a" and X.a.x == 4 and X.a._M == X.a)
+module("X.a.b", package.seeall); assert(x == 3); x = 5
+assert(_NAME == "X.a.b" and X.a.b.x == 5)
+
+assert(X._G == nil and X.a._G == nil and X.a.b._G == _G and X.a.b.c._G == nil)
+
+setfenv(1, _G)
+assert(x == 0)
+
+assert(not pcall(module, "x"))
+assert(not pcall(module, "math.sin"))
+
+
+-- testing C libraries
+
+
+local p = "" -- On Mac OS X, redefine this to "_"
+
+-- assert(loadlib == package.loadlib) -- only for compatibility
+local f, err, when = package.loadlib("libs/lib1.so", p.."luaopen_lib1")
+if not f then
+ (Message or print)('\a\n >>> cannot load dynamic library <<<\n\a')
+ print(err, when)
+else
+ f() -- open library
+ assert(require("lib1") == lib1)
+ collectgarbage()
+ assert(lib1.id("x") == "x")
+ f = assert(package.loadlib("libs/lib1.so", p.."anotherfunc"))
+ assert(f(10, 20) == "1020\n")
+ f, err, when = package.loadlib("libs/lib1.so", p.."xuxu")
+ assert(not f and type(err) == "string" and when == "init")
+ package.cpath = "libs/?.so"
+ require"lib2"
+ assert(lib2.id("x") == "x")
+ local fs = require"lib1.sub"
+ assert(fs == lib1.sub and next(lib1.sub) == nil)
+ module("lib2", package.seeall)
+ f = require"-lib2"
+ assert(f.id("x") == "x" and _M == f and _NAME == "lib2")
+ module("lib1.sub", package.seeall)
+ assert(_M == fs)
+ setfenv(1, _G)
+
+end
+f, err, when = package.loadlib("donotexist", p.."xuxu")
+assert(not f and type(err) == "string" and (when == "open" or when == "absent"))
+
+
+-- testing preload
+
+do
+ local p = package
+ package = {}
+ p.preload.pl = function (...)
+ module(...)
+ function xuxu (x) return x+20 end
+ end
+
+ require"pl"
+ assert(require"pl" == pl)
+ assert(pl.xuxu(10) == 30)
+
+ package = p
+ assert(type(package.path) == "string")
+end
+
+
+
+end --]
+
+print('+')
+
+print("testing assignments, logical operators, and constructors")
+
+local res, res2 = 27
+
+a, b = 1, 2+3
+assert(a==1 and b==5)
+a={}
+function f() return 10, 11, 12 end
+a.x, b, a[1] = 1, 2, f()
+assert(a.x==1 and b==2 and a[1]==10)
+a[f()], b, a[f()+3] = f(), a, 'x'
+assert(a[10] == 10 and b == a and a[13] == 'x')
+
+do
+ local f = function (n) local x = {}; for i=1,n do x[i]=i end;
+ return unpack(x) end;
+ local a,b,c
+ a,b = 0, f(1)
+ assert(a == 0 and b == 1)
+ A,b = 0, f(1)
+ assert(A == 0 and b == 1)
+ a,b,c = 0,5,f(4)
+ assert(a==0 and b==5 and c==1)
+ a,b,c = 0,5,f(0)
+ assert(a==0 and b==5 and c==nil)
+end
+
+
+a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
+assert(not a and b and c and d==6)
+
+d = 20
+a, b, c, d = f()
+assert(a==10 and b==11 and c==12 and d==nil)
+a,b = f(), 1, 2, 3, f()
+assert(a==10 and b==1)
+
+assert(a<b == false and a>b == true)
+assert((10 and 2) == 2)
+assert((10 or 2) == 10)
+assert((10 or assert(nil)) == 10)
+assert(not (nil and assert(nil)))
+assert((nil or "alo") == "alo")
+assert((nil and 10) == nil)
+assert((false and 10) == false)
+assert((true or 10) == true)
+assert((false or 10) == 10)
+assert(false ~= nil)
+assert(nil ~= false)
+assert(not nil == true)
+assert(not not nil == false)
+assert(not not 1 == true)
+assert(not not a == true)
+assert(not not (6 or nil) == true)
+assert(not not (nil and 56) == false)
+assert(not not (nil and true) == false)
+print('+')
+
+a = {}
+a[true] = 20
+a[false] = 10
+assert(a[1<2] == 20 and a[1>2] == 10)
+
+function f(a) return a end
+
+local a = {}
+for i=3000,-3000,-1 do a[i] = i; end
+a[10e30] = "alo"; a[true] = 10; a[false] = 20
+assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
+for i=3000,-3000,-1 do assert(a[i] == i); end
+a[print] = assert
+a[f] = print
+a[a] = a
+assert(a[a][a][a][a][print] == assert)
+a[print](a[a[f]] == a[print])
+a = nil
+
+a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
+a, a.x, a.y = a, a[-3]
+assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
+a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
+a[1].alo(a[2]==10 and b==10 and c==print)
+
+a[2^31] = 10; a[2^31+1] = 11; a[-2^31] = 12;
+a[2^32] = 13; a[-2^32] = 14; a[2^32+1] = 15; a[10^33] = 16;
+
+assert(a[2^31] == 10 and a[2^31+1] == 11 and a[-2^31] == 12 and
+ a[2^32] == 13 and a[-2^32] == 14 and a[2^32+1] == 15 and
+ a[10^33] == 16)
+
+a = nil
+
+
+do
+ local a,i,j,b
+ a = {'a', 'b'}; i=1; j=2; b=a
+ i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
+ assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
+ b[3] == 1)
+end
+
+print('OK')
+
+return res
diff --git a/test/PUC-Lua-5.1-tests/big.lua b/test/PUC-Lua-5.1-tests/big.lua
new file mode 100644
index 0000000..9261288
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/big.lua
@@ -0,0 +1,381 @@
+print "testing string length overflow"
+
+local longs = string.rep("\0", 2^25)
+local function catter (i)
+ return assert(loadstring(
+ string.format("return function(a) return a%s end",
+ string.rep("..a", i-1))))()
+end
+rep129 = catter(129)
+local a, b = pcall(rep129, longs)
+assert(not a and string.find(b, "overflow"))
+print('+')
+
+
+require "checktable"
+
+--[[ lots of empty lines (to force SETLINEW)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+--]]
+
+
+a,b = nil,nil
+while not b do
+if a then
+b = { -- lots of strings (to force JMPW and PUSHCONSTANTW)
+"n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9", "n10",
+"n11", "n12", "j301", "j302", "j303", "j304", "j305", "j306", "j307", "j308",
+"j309", "a310", "n311", "n312", "n313", "n314", "n315", "n316", "n317", "n318",
+"n319", "n320", "n321", "n322", "n323", "n324", "n325", "n326", "n327", "n328",
+"a329", "n330", "n331", "n332", "n333", "n334", "n335", "n336", "n337", "n338",
+"n339", "n340", "n341", "z342", "n343", "n344", "n345", "n346", "n347", "n348",
+"n349", "n350", "n351", "n352", "r353", "n354", "n355", "n356", "n357", "n358",
+"n359", "n360", "n361", "n362", "n363", "n364", "n365", "n366", "z367", "n368",
+"n369", "n370", "n371", "n372", "n373", "n374", "n375", "a376", "n377", "n378",
+"n379", "n380", "n381", "n382", "n383", "n384", "n385", "n386", "n387", "n388",
+"n389", "n390", "n391", "n392", "n393", "n394", "n395", "n396", "n397", "n398",
+"n399", "n400", "n13", "n14", "n15", "n16", "n17", "n18", "n19", "n20",
+"n21", "n22", "n23", "a24", "n25", "n26", "n27", "n28", "n29", "j30",
+"n31", "n32", "n33", "n34", "n35", "n36", "n37", "n38", "n39", "n40",
+"n41", "n42", "n43", "n44", "n45", "n46", "n47", "n48", "n49", "n50",
+"n51", "n52", "n53", "n54", "n55", "n56", "n57", "n58", "n59", "n60",
+"n61", "n62", "n63", "n64", "n65", "a66", "z67", "n68", "n69", "n70",
+"n71", "n72", "n73", "n74", "n75", "n76", "n77", "n78", "n79", "n80",
+"n81", "n82", "n83", "n84", "n85", "n86", "n87", "n88", "n89", "n90",
+"n91", "n92", "n93", "n94", "n95", "n96", "n97", "n98", "n99", "n100",
+"n201", "n202", "n203", "n204", "n205", "n206", "n207", "n208", "n209", "n210",
+"n211", "n212", "n213", "n214", "n215", "n216", "n217", "n218", "n219", "n220",
+"n221", "n222", "n223", "n224", "n225", "n226", "n227", "n228", "n229", "n230",
+"n231", "n232", "n233", "n234", "n235", "n236", "n237", "n238", "n239", "a240",
+"a241", "a242", "a243", "a244", "a245", "a246", "a247", "a248", "a249", "n250",
+"n251", "n252", "n253", "n254", "n255", "n256", "n257", "n258", "n259", "n260",
+"n261", "n262", "n263", "n264", "n265", "n266", "n267", "n268", "n269", "n270",
+"n271", "n272", "n273", "n274", "n275", "n276", "n277", "n278", "n279", "n280",
+"n281", "n282", "n283", "n284", "n285", "n286", "n287", "n288", "n289", "n290",
+"n291", "n292", "n293", "n294", "n295", "n296", "n297", "n298", "n299"
+; x=23}
+else a = 1 end
+
+
+end
+
+assert(b.x == 23)
+print('+')
+
+stat(b)
+
+repeat
+a = {
+n1 = 1.5, n2 = 2.5, n3 = 3.5, n4 = 4.5, n5 = 5.5, n6 = 6.5, n7 = 7.5,
+n8 = 8.5, n9 = 9.5, n10 = 10.5, n11 = 11.5, n12 = 12.5,
+j301 = 301.5, j302 = 302.5, j303 = 303.5, j304 = 304.5, j305 = 305.5,
+j306 = 306.5, j307 = 307.5, j308 = 308.5, j309 = 309.5, a310 = 310.5,
+n311 = 311.5, n312 = 312.5, n313 = 313.5, n314 = 314.5, n315 = 315.5,
+n316 = 316.5, n317 = 317.5, n318 = 318.5, n319 = 319.5, n320 = 320.5,
+n321 = 321.5, n322 = 322.5, n323 = 323.5, n324 = 324.5, n325 = 325.5,
+n326 = 326.5, n327 = 327.5, n328 = 328.5, a329 = 329.5, n330 = 330.5,
+n331 = 331.5, n332 = 332.5, n333 = 333.5, n334 = 334.5, n335 = 335.5,
+n336 = 336.5, n337 = 337.5, n338 = 338.5, n339 = 339.5, n340 = 340.5,
+n341 = 341.5, z342 = 342.5, n343 = 343.5, n344 = 344.5, n345 = 345.5,
+n346 = 346.5, n347 = 347.5, n348 = 348.5, n349 = 349.5, n350 = 350.5,
+n351 = 351.5, n352 = 352.5, r353 = 353.5, n354 = 354.5, n355 = 355.5,
+n356 = 356.5, n357 = 357.5, n358 = 358.5, n359 = 359.5, n360 = 360.5,
+n361 = 361.5, n362 = 362.5, n363 = 363.5, n364 = 364.5, n365 = 365.5,
+n366 = 366.5, z367 = 367.5, n368 = 368.5, n369 = 369.5, n370 = 370.5,
+n371 = 371.5, n372 = 372.5, n373 = 373.5, n374 = 374.5, n375 = 375.5,
+a376 = 376.5, n377 = 377.5, n378 = 378.5, n379 = 379.5, n380 = 380.5,
+n381 = 381.5, n382 = 382.5, n383 = 383.5, n384 = 384.5, n385 = 385.5,
+n386 = 386.5, n387 = 387.5, n388 = 388.5, n389 = 389.5, n390 = 390.5,
+n391 = 391.5, n392 = 392.5, n393 = 393.5, n394 = 394.5, n395 = 395.5,
+n396 = 396.5, n397 = 397.5, n398 = 398.5, n399 = 399.5, n400 = 400.5,
+n13 = 13.5, n14 = 14.5, n15 = 15.5, n16 = 16.5, n17 = 17.5,
+n18 = 18.5, n19 = 19.5, n20 = 20.5, n21 = 21.5, n22 = 22.5,
+n23 = 23.5, a24 = 24.5, n25 = 25.5, n26 = 26.5, n27 = 27.5,
+n28 = 28.5, n29 = 29.5, j30 = 30.5, n31 = 31.5, n32 = 32.5,
+n33 = 33.5, n34 = 34.5, n35 = 35.5, n36 = 36.5, n37 = 37.5,
+n38 = 38.5, n39 = 39.5, n40 = 40.5, n41 = 41.5, n42 = 42.5,
+n43 = 43.5, n44 = 44.5, n45 = 45.5, n46 = 46.5, n47 = 47.5,
+n48 = 48.5, n49 = 49.5, n50 = 50.5, n51 = 51.5, n52 = 52.5,
+n53 = 53.5, n54 = 54.5, n55 = 55.5, n56 = 56.5, n57 = 57.5,
+n58 = 58.5, n59 = 59.5, n60 = 60.5, n61 = 61.5, n62 = 62.5,
+n63 = 63.5, n64 = 64.5, n65 = 65.5, a66 = 66.5, z67 = 67.5,
+n68 = 68.5, n69 = 69.5, n70 = 70.5, n71 = 71.5, n72 = 72.5,
+n73 = 73.5, n74 = 74.5, n75 = 75.5, n76 = 76.5, n77 = 77.5,
+n78 = 78.5, n79 = 79.5, n80 = 80.5, n81 = 81.5, n82 = 82.5,
+n83 = 83.5, n84 = 84.5, n85 = 85.5, n86 = 86.5, n87 = 87.5,
+n88 = 88.5, n89 = 89.5, n90 = 90.5, n91 = 91.5, n92 = 92.5,
+n93 = 93.5, n94 = 94.5, n95 = 95.5, n96 = 96.5, n97 = 97.5,
+n98 = 98.5, n99 = 99.5, n100 = 100.5, n201 = 201.5, n202 = 202.5,
+n203 = 203.5, n204 = 204.5, n205 = 205.5, n206 = 206.5, n207 = 207.5,
+n208 = 208.5, n209 = 209.5, n210 = 210.5, n211 = 211.5, n212 = 212.5,
+n213 = 213.5, n214 = 214.5, n215 = 215.5, n216 = 216.5, n217 = 217.5,
+n218 = 218.5, n219 = 219.5, n220 = 220.5, n221 = 221.5, n222 = 222.5,
+n223 = 223.5, n224 = 224.5, n225 = 225.5, n226 = 226.5, n227 = 227.5,
+n228 = 228.5, n229 = 229.5, n230 = 230.5, n231 = 231.5, n232 = 232.5,
+n233 = 233.5, n234 = 234.5, n235 = 235.5, n236 = 236.5, n237 = 237.5,
+n238 = 238.5, n239 = 239.5, a240 = 240.5, a241 = 241.5, a242 = 242.5,
+a243 = 243.5, a244 = 244.5, a245 = 245.5, a246 = 246.5, a247 = 247.5,
+a248 = 248.5, a249 = 249.5, n250 = 250.5, n251 = 251.5, n252 = 252.5,
+n253 = 253.5, n254 = 254.5, n255 = 255.5, n256 = 256.5, n257 = 257.5,
+n258 = 258.5, n259 = 259.5, n260 = 260.5, n261 = 261.5, n262 = 262.5,
+n263 = 263.5, n264 = 264.5, n265 = 265.5, n266 = 266.5, n267 = 267.5,
+n268 = 268.5, n269 = 269.5, n270 = 270.5, n271 = 271.5, n272 = 272.5,
+n273 = 273.5, n274 = 274.5, n275 = 275.5, n276 = 276.5, n277 = 277.5,
+n278 = 278.5, n279 = 279.5, n280 = 280.5, n281 = 281.5, n282 = 282.5,
+n283 = 283.5, n284 = 284.5, n285 = 285.5, n286 = 286.5, n287 = 287.5,
+n288 = 288.5, n289 = 289.5, n290 = 290.5, n291 = 291.5, n292 = 292.5,
+n293 = 293.5, n294 = 294.5, n295 = 295.5, n296 = 296.5, n297 = 297.5,
+n298 = 298.5, n299 = 299.5, j300 = 300} or 1
+until 1
+
+assert(a.n299 == 299.5)
+xxx = 1
+assert(xxx == 1)
+
+stat(a)
+
+function a:findfield (f)
+ local i,v = next(self, nil)
+ while i ~= f do
+ if not i then return end
+ i,v = next(self, i)
+ end
+ return v
+end
+
+local ii = 0
+i = 1
+while b[i] do
+ local r = a:findfield(b[i]);
+ assert(a[b[i]] == r)
+ ii = math.max(ii,i)
+ i = i+1
+end
+
+assert(ii == 299)
+
+function xxxx (x) coroutine.yield('b'); return ii+x end
+
+assert(xxxx(10) == 309)
+
+a = nil
+b = nil
+a1 = nil
+
+print("tables with table indices:")
+i = 1; a={}
+while i <= 1023 do a[{}] = i; i=i+1 end
+stat(a)
+a = nil
+
+print("tables with function indices:")
+a={}
+for i=1,511 do local x; a[function () return x end] = i end
+stat(a)
+a = nil
+
+print'OK'
+
+return 'a'
diff --git a/test/PUC-Lua-5.1-tests/calls.lua b/test/PUC-Lua-5.1-tests/calls.lua
new file mode 100644
index 0000000..788f9a1
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/calls.lua
@@ -0,0 +1,294 @@
+print("testing functions and calls")
+
+-- get the opportunity to test 'type' too ;)
+
+assert(type(1<2) == 'boolean')
+assert(type(true) == 'boolean' and type(false) == 'boolean')
+assert(type(nil) == 'nil' and type(-3) == 'number' and type'x' == 'string' and
+ type{} == 'table' and type(type) == 'function')
+
+assert(type(assert) == type(print))
+f = nil
+function f (x) return a:x (x) end
+assert(type(f) == 'function')
+
+
+-- testing local-function recursion
+fact = false
+do
+ local res = 1
+ local function fact (n)
+ if n==0 then return res
+ else return n*fact(n-1)
+ end
+ end
+ assert(fact(5) == 120)
+end
+assert(fact == false)
+
+-- testing declarations
+a = {i = 10}
+self = 20
+function a:x (x) return x+self.i end
+function a.y (x) return x+self end
+
+assert(a:x(1)+10 == a.y(1))
+
+a.t = {i=-100}
+a["t"].x = function (self, a,b) return self.i+a+b end
+
+assert(a.t:x(2,3) == -95)
+
+do
+ local a = {x=0}
+ function a:add (x) self.x, a.y = self.x+x, 20; return self end
+ assert(a:add(10):add(20):add(30).x == 60 and a.y == 20)
+end
+
+local a = {b={c={}}}
+
+function a.b.c.f1 (x) return x+1 end
+function a.b.c:f2 (x,y) self[x] = y end
+assert(a.b.c.f1(4) == 5)
+a.b.c:f2('k', 12); assert(a.b.c.k == 12)
+
+print('+')
+
+t = nil -- 'declare' t
+function f(a,b,c) local d = 'a'; t={a,b,c,d} end
+
+f( -- this line change must be valid
+ 1,2)
+assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a')
+f(1,2, -- this one too
+ 3,4)
+assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
+
+function fat(x)
+ if x <= 1 then return 1
+ else return x*loadstring("return fat(" .. x-1 .. ")")()
+ end
+end
+
+assert(loadstring "loadstring 'assert(fat(6)==720)' () ")()
+a = loadstring('return fat(5), 3')
+a,b = a()
+assert(a == 120 and b == 3)
+print('+')
+
+function err_on_n (n)
+ if n==0 then error(); exit(1);
+ else err_on_n (n-1); exit(1);
+ end
+end
+
+do
+ function dummy (n)
+ if n > 0 then
+ assert(not pcall(err_on_n, n))
+ dummy(n-1)
+ end
+ end
+end
+
+dummy(10)
+
+function deep (n)
+ if n>0 then deep(n-1) end
+end
+deep(10)
+deep(200)
+
+-- testing tail call
+function deep (n) if n>0 then return deep(n-1) else return 101 end end
+assert(deep(30000) == 101)
+a = {}
+function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end
+assert(a:deep(30000) == 101)
+
+print('+')
+
+
+a = nil
+(function (x) a=x end)(23)
+assert(a == 23 and (function (x) return x*2 end)(20) == 40)
+
+
+local x,y,z,a
+a = {}; lim = 2000
+for i=1, lim do a[i]=i end
+assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
+x = unpack(a)
+assert(x == 1)
+x = {unpack(a)}
+assert(table.getn(x) == lim and x[1] == 1 and x[lim] == lim)
+x = {unpack(a, lim-2)}
+assert(table.getn(x) == 3 and x[1] == lim-2 and x[3] == lim)
+x = {unpack(a, 10, 6)}
+assert(next(x) == nil) -- no elements
+x = {unpack(a, 11, 10)}
+assert(next(x) == nil) -- no elements
+x,y = unpack(a, 10, 10)
+assert(x == 10 and y == nil)
+x,y,z = unpack(a, 10, 11)
+assert(x == 10 and y == 11 and z == nil)
+a,x = unpack{1}
+assert(a==1 and x==nil)
+a,x = unpack({1,2}, 1, 1)
+assert(a==1 and x==nil)
+
+
+-- testing closures
+
+-- fixed-point operator
+Y = function (le)
+ local function a (f)
+ return le(function (x) return f(f)(x) end)
+ end
+ return a(a)
+ end
+
+
+-- non-recursive factorial
+
+F = function (f)
+ return function (n)
+ if n == 0 then return 1
+ else return n*f(n-1) end
+ end
+ end
+
+fat = Y(F)
+
+assert(fat(0) == 1 and fat(4) == 24 and Y(F)(5)==5*Y(F)(4))
+
+local function g (z)
+ local function f (a,b,c,d)
+ return function (x,y) return a+b+c+d+a+x+y+z end
+ end
+ return f(z,z+1,z+2,z+3)
+end
+
+f = g(10)
+assert(f(9, 16) == 10+11+12+13+10+9+16+10)
+
+Y, F, f = nil
+print('+')
+
+-- testing multiple returns
+
+function unlpack (t, i)
+ i = i or 1
+ if (i <= table.getn(t)) then
+ return t[i], unlpack(t, i+1)
+ end
+end
+
+function equaltab (t1, t2)
+ assert(table.getn(t1) == table.getn(t2))
+ for i,v1 in ipairs(t1) do
+ assert(v1 == t2[i])
+ end
+end
+
+local function pack (...)
+ local x = {...}
+ x.n = select('#', ...)
+ return x
+end
+
+function f() return 1,2,30,4 end
+function ret2 (a,b) return a,b end
+
+local a,b,c,d = unlpack{1,2,3}
+assert(a==1 and b==2 and c==3 and d==nil)
+a = {1,2,3,4,false,10,'alo',false,assert}
+equaltab(pack(unlpack(a)), a)
+equaltab(pack(unlpack(a), -1), {1,-1})
+a,b,c,d = ret2(f()), ret2(f())
+assert(a==1 and b==1 and c==2 and d==nil)
+a,b,c,d = unlpack(pack(ret2(f()), ret2(f())))
+assert(a==1 and b==1 and c==2 and d==nil)
+a,b,c,d = unlpack(pack(ret2(f()), (ret2(f()))))
+assert(a==1 and b==1 and c==nil and d==nil)
+
+a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}}
+assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b")
+
+
+-- testing calls with 'incorrect' arguments
+rawget({}, "x", 1)
+rawset({}, "x", 1, 2)
+assert(math.sin(1,2) == math.sin(1))
+table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
+
+
+-- test for generic load
+x = "-- a comment\0\0\0\n x = 10 + \n23; \
+ local a = function () x = 'hi' end; \
+ return '\0'"
+local i = 0
+function read1 (x)
+ return function ()
+ collectgarbage()
+ i=i+1
+ return string.sub(x, i, i)
+ end
+end
+
+a = assert(load(read1(x), "modname"))
+assert(a() == "\0" and _G.x == 33)
+assert(debug.getinfo(a).source == "modname")
+
+x = string.dump(loadstring("x = 1; return x"))
+i = 0
+a = assert(load(read1(x)))
+assert(a() == 1 and _G.x == 1)
+
+i = 0
+local a, b = load(read1("*a = 123"))
+assert(not a and type(b) == "string" and i == 2)
+
+a, b = load(function () error("hhi") end)
+assert(not a and string.find(b, "hhi"))
+
+-- test generic load with nested functions
+x = [[
+ return function (x)
+ return function (y)
+ return function (z)
+ return x+y+z
+ end
+ end
+ end
+]]
+
+a = assert(load(read1(x)))
+assert(a()(2)(3)(10) == 15)
+
+
+-- test for dump/undump with upvalues
+local a, b = 20, 30
+x = loadstring(string.dump(function (x)
+ if x == "set" then a = 10+b; b = b+1 else
+ return a
+ end
+end))
+assert(x() == nil)
+assert(debug.setupvalue(x, 1, "hi") == "a")
+assert(x() == "hi")
+assert(debug.setupvalue(x, 2, 13) == "b")
+assert(not debug.setupvalue(x, 3, 10)) -- only 2 upvalues
+x("set")
+assert(x() == 23)
+x("set")
+assert(x() == 24)
+
+
+-- test for bug in parameter adjustment
+assert((function () return nil end)(4) == nil)
+assert((function () local a; return a end)(4) == nil)
+assert((function (a) return a end)() == nil)
+
+print('OK')
+return deep
diff --git a/test/PUC-Lua-5.1-tests/checktable.lua b/test/PUC-Lua-5.1-tests/checktable.lua
new file mode 100644
index 0000000..f0938be
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/checktable.lua
@@ -0,0 +1,77 @@
+
+assert(rawget(_G, "stat") == nil) -- module not loaded before
+
+if T == nil then
+ stat = function () print"`querytab' nao ativo" end
+ return
+end
+
+
+function checktable (t)
+ local asize, hsize, ff = T.querytab(t)
+ local l = {}
+ for i=0,hsize-1 do
+ local key,val,next = T.querytab(t, i + asize)
+ if key == nil then
+ assert(l[i] == nil and val==nil and next==nil)
+ elseif key == "<undef>" then
+ assert(val==nil)
+ else
+ assert(t[key] == val)
+ local mp = T.hash(key, t)
+ if l[i] then
+ assert(l[i] == mp)
+ elseif mp ~= i then
+ l[i] = mp
+ else -- list head
+ l[mp] = {mp} -- first element
+ while next do
+ assert(ff <= next and next < hsize)
+ if l[next] then assert(l[next] == mp) else l[next] = mp end
+ table.insert(l[mp], next)
+ key,val,next = T.querytab(t, next)
+ assert(key)
+ end
+ end
+ end
+ end
+ l.asize = asize; l.hsize = hsize; l.ff = ff
+ return l
+end
+
+function mostra (t)
+ local asize, hsize, ff = T.querytab(t)
+ print(asize, hsize, ff)
+ print'------'
+ for i=0,asize-1 do
+ local _, v = T.querytab(t, i)
+ print(string.format("[%d] -", i), v)
+ end
+ print'------'
+ for i=0,hsize-1 do
+ print(i, T.querytab(t, i+asize))
+ end
+ print'-------------'
+end
+
+function stat (t)
+ t = checktable(t)
+ local nelem, nlist = 0, 0
+ local maxlist = {}
+ for i=0,t.hsize-1 do
+ if type(t[i]) == 'table' then
+ local n = table.getn(t[i])
+ nlist = nlist+1
+ nelem = nelem + n
+ if not maxlist[n] then maxlist[n] = 0 end
+ maxlist[n] = maxlist[n]+1
+ end
+ end
+ print(string.format("hsize=%d elements=%d load=%.2f med.len=%.2f (asize=%d)",
+ t.hsize, nelem, nelem/t.hsize, nelem/nlist, t.asize))
+ for i=1,table.getn(maxlist) do
+ local n = maxlist[i] or 0
+ print(string.format("%5d %10d %.2f%%", i, n, n*100/nlist))
+ end
+end
+
diff --git a/test/PUC-Lua-5.1-tests/closure.lua b/test/PUC-Lua-5.1-tests/closure.lua
new file mode 100644
index 0000000..27ca0ad
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/closure.lua
@@ -0,0 +1,422 @@
+print "testing closures and coroutines"
+
+local A,B = 0,{g=10}
+function f(x)
+ local a = {}
+ for i=1,1000 do
+ local y = 0
+ do
+ a[i] = function () B.g = B.g+1; y = y+x; return y+A end
+ end
+ end
+ local dummy = function () return a[A] end
+ collectgarbage()
+ A = 1; assert(dummy() == a[1]); A = 0;
+ assert(a[1]() == x)
+ assert(a[3]() == x)
+ collectgarbage()
+ assert(B.g == 12)
+ return a
+end
+
+a = f(10)
+-- force a GC in this level
+local x = {[1] = {}} -- to detect a GC
+setmetatable(x, {__mode = 'kv'})
+while x[1] do -- repeat until GC
+ local a = A..A..A..A -- create garbage
+ A = A+1
+end
+assert(a[1]() == 20+A)
+assert(a[1]() == 30+A)
+assert(a[2]() == 10+A)
+collectgarbage()
+assert(a[2]() == 20+A)
+assert(a[2]() == 30+A)
+assert(a[3]() == 20+A)
+assert(a[8]() == 10+A)
+assert(getmetatable(x).__mode == 'kv')
+assert(B.g == 19)
+
+-- testing closures with 'for' control variable
+a = {}
+for i=1,10 do
+ a[i] = {set = function(x) i=x end, get = function () return i end}
+ if i == 3 then break end
+end
+assert(a[4] == nil)
+a[1].set(10)
+assert(a[2].get() == 2)
+a[2].set('a')
+assert(a[3].get() == 3)
+assert(a[2].get() == 'a')
+
+a = {}
+for i, k in pairs{'a', 'b'} do
+ a[i] = {set = function(x, y) i=x; k=y end,
+ get = function () return i, k end}
+ if i == 2 then break end
+end
+a[1].set(10, 20)
+local r,s = a[2].get()
+assert(r == 2 and s == 'b')
+r,s = a[1].get()
+assert(r == 10 and s == 20)
+a[2].set('a', 'b')
+r,s = a[2].get()
+assert(r == "a" and s == "b")
+
+
+-- testing closures with 'for' control variable x break
+for i=1,3 do
+ f = function () return i end
+ break
+end
+assert(f() == 1)
+
+for k, v in pairs{"a", "b"} do
+ f = function () return k, v end
+ break
+end
+assert(({f()})[1] == 1)
+assert(({f()})[2] == "a")
+
+
+-- testing closure x break x return x errors
+
+local b
+function f(x)
+ local first = 1
+ while 1 do
+ if x == 3 and not first then return end
+ local a = 'xuxu'
+ b = function (op, y)
+ if op == 'set' then
+ a = x+y
+ else
+ return a
+ end
+ end
+ if x == 1 then do break end
+ elseif x == 2 then return
+ else if x ~= 3 then error() end
+ end
+ first = nil
+ end
+end
+
+for i=1,3 do
+ f(i)
+ assert(b('get') == 'xuxu')
+ b('set', 10); assert(b('get') == 10+i)
+ b = nil
+end
+
+pcall(f, 4);
+assert(b('get') == 'xuxu')
+b('set', 10); assert(b('get') == 14)
+
+
+local w
+-- testing multi-level closure
+function f(x)
+ return function (y)
+ return function (z) return w+x+y+z end
+ end
+end
+
+y = f(10)
+w = 1.345
+assert(y(20)(30) == 60+w)
+
+-- testing closures x repeat-until
+
+local a = {}
+local i = 1
+repeat
+ local x = i
+ a[i] = function () i = x+1; return x end
+until i > 10 or a[i]() ~= x
+assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
+
+print'+'
+
+
+-- test for correctly closing upvalues in tail calls of vararg functions
+local function t ()
+ local function c(a,b) assert(a=="test" and b=="OK") end
+ local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
+ local x = 1
+ return v(function() return x end)
+end
+t()
+
+
+-- coroutine tests
+
+local f
+
+assert(coroutine.running() == nil)
+
+
+-- tests for global environment
+
+local function foo (a)
+ setfenv(0, a)
+ coroutine.yield(getfenv())
+ assert(getfenv(0) == a)
+ assert(getfenv(1) == _G)
+ assert(getfenv(loadstring"") == a)
+ return getfenv()
+end
+
+f = coroutine.wrap(foo)
+local a = {}
+assert(f(a) == _G)
+local a,b = pcall(f)
+assert(a and b == _G)
+
+
+-- tests for multiple yield/resume arguments
+
+local function eqtab (t1, t2)
+ assert(table.getn(t1) == table.getn(t2))
+ for i,v in ipairs(t1) do
+ assert(t2[i] == v)
+ end
+end
+
+_G.x = nil -- declare x
+function foo (a, ...)
+ assert(coroutine.running() == f)
+ assert(coroutine.status(f) == "running")
+ local arg = {...}
+ for i=1,table.getn(arg) do
+ _G.x = {coroutine.yield(unpack(arg[i]))}
+ end
+ return unpack(a)
+end
+
+f = coroutine.create(foo)
+assert(type(f) == "thread" and coroutine.status(f) == "suspended")
+assert(string.find(tostring(f), "thread"))
+local s,a,b,c,d
+s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
+assert(s and a == nil and coroutine.status(f) == "suspended")
+s,a,b,c,d = coroutine.resume(f)
+eqtab(_G.x, {})
+assert(s and a == 1 and b == nil)
+s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
+eqtab(_G.x, {1, 2, 3})
+assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
+s,a,b,c,d = coroutine.resume(f, "xuxu")
+eqtab(_G.x, {"xuxu"})
+assert(s and a == 1 and b == 2 and c == 3 and d == nil)
+assert(coroutine.status(f) == "dead")
+s, a = coroutine.resume(f, "xuxu")
+assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
+
+
+-- yields in tail calls
+local function foo (i) return coroutine.yield(i) end
+f = coroutine.wrap(function ()
+ for i=1,10 do
+ assert(foo(i) == _G.x)
+ end
+ return 'a'
+end)
+for i=1,10 do _G.x = i; assert(f(i) == i) end
+_G.x = 'xuxu'; assert(f('xuxu') == 'a')
+
+-- recursive
+function pf (n, i)
+ coroutine.yield(n)
+ pf(n*i, i+1)
+end
+
+f = coroutine.wrap(pf)
+local s=1
+for i=1,10 do
+ assert(f(1, 1) == s)
+ s = s*i
+end
+
+-- sieve
+function gen (n)
+ return coroutine.wrap(function ()
+ for i=2,n do coroutine.yield(i) end
+ end)
+end
+
+
+function filter (p, g)
+ return coroutine.wrap(function ()
+ while 1 do
+ local n = g()
+ if n == nil then return end
+ if math.mod(n, p) ~= 0 then coroutine.yield(n) end
+ end
+ end)
+end
+
+local x = gen(100)
+local a = {}
+while 1 do
+ local n = x()
+ if n == nil then break end
+ table.insert(a, n)
+ x = filter(n, x)
+end
+
+assert(table.getn(a) == 25 and a[table.getn(a)] == 97)
+
+
+-- errors in coroutines
+function foo ()
+ assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
+ assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
+ coroutine.yield(3)
+ error(foo)
+end
+
+function goo() foo() end
+x = coroutine.wrap(goo)
+assert(x() == 3)
+local a,b = pcall(x)
+assert(not a and b == foo)
+
+x = coroutine.create(goo)
+a,b = coroutine.resume(x)
+assert(a and b == 3)
+a,b = coroutine.resume(x)
+assert(not a and b == foo and coroutine.status(x) == "dead")
+a,b = coroutine.resume(x)
+assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
+
+
+-- co-routines x for loop
+function all (a, n, k)
+ if k == 0 then coroutine.yield(a)
+ else
+ for i=1,n do
+ a[k] = i
+ all(a, n, k-1)
+ end
+ end
+end
+
+local a = 0
+for t in coroutine.wrap(function () all({}, 5, 4) end) do
+ a = a+1
+end
+assert(a == 5^4)
+
+
+-- access to locals of collected corroutines
+local C = {}; setmetatable(C, {__mode = "kv"})
+local x = coroutine.wrap (function ()
+ local a = 10
+ local function f () a = a+10; return a end
+ while true do
+ a = a+1
+ coroutine.yield(f)
+ end
+ end)
+
+C[1] = x;
+
+local f = x()
+assert(f() == 21 and x()() == 32 and x() == f)
+x = nil
+collectgarbage()
+assert(C[1] == nil)
+assert(f() == 43 and f() == 53)
+
+
+-- old bug: attempt to resume itself
+
+function co_func (current_co)
+ assert(coroutine.running() == current_co)
+ assert(coroutine.resume(current_co) == false)
+ assert(coroutine.resume(current_co) == false)
+ return 10
+end
+
+local co = coroutine.create(co_func)
+local a,b = coroutine.resume(co, co)
+assert(a == true and b == 10)
+assert(coroutine.resume(co, co) == false)
+assert(coroutine.resume(co, co) == false)
+
+-- access to locals of erroneous coroutines
+local x = coroutine.create (function ()
+ local a = 10
+ _G.f = function () a=a+1; return a end
+ error('x')
+ end)
+
+assert(not coroutine.resume(x))
+-- overwrite previous position of local `a'
+assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
+assert(_G.f() == 11)
+assert(_G.f() == 12)
+
+
+if not T then
+ (Message or print)('\a\n >>> testC not active: skipping yield/hook tests <<<\n\a')
+else
+
+ local turn
+
+ function fact (t, x)
+ assert(turn == t)
+ if x == 0 then return 1
+ else return x*fact(t, x-1)
+ end
+ end
+
+ local A,B,a,b = 0,0,0,0
+
+ local x = coroutine.create(function ()
+ T.setyhook("", 2)
+ A = fact("A", 10)
+ end)
+
+ local y = coroutine.create(function ()
+ T.setyhook("", 3)
+ B = fact("B", 11)
+ end)
+
+ while A==0 or B==0 do
+ if A==0 then turn = "A"; T.resume(x) end
+ if B==0 then turn = "B"; T.resume(y) end
+ end
+
+ assert(B/A == 11)
+end
+
+
+-- leaving a pending coroutine open
+_X = coroutine.wrap(function ()
+ local a = 10
+ local x = function () a = a+1 end
+ coroutine.yield()
+ end)
+
+_X()
+
+
+-- coroutine environments
+co = coroutine.create(function ()
+ coroutine.yield(getfenv(0))
+ return loadstring("return a")()
+ end)
+
+a = {a = 15}
+debug.setfenv(co, a)
+assert(debug.getfenv(co) == a)
+assert(select(2, coroutine.resume(co)) == a)
+assert(select(2, coroutine.resume(co)) == a.a)
+
+
+print'OK'
diff --git a/test/PUC-Lua-5.1-tests/code.lua b/test/PUC-Lua-5.1-tests/code.lua
new file mode 100644
index 0000000..875d488
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/code.lua
@@ -0,0 +1,143 @@
+
+if T==nil then
+ (Message or print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a')
+ return
+end
+print "testing code generation and optimizations"
+
+
+-- this code gave an error for the code checker
+do
+ local function f (a)
+ for k,v,w in a do end
+ end
+end
+
+
+function check (f, ...)
+ local c = T.listcode(f)
+ for i=1, arg.n do
+ -- print(arg[i], c[i])
+ assert(string.find(c[i], '- '..arg[i]..' *%d'))
+ end
+ assert(c[arg.n+2] == nil)
+end
+
+
+function checkequal (a, b)
+ a = T.listcode(a)
+ b = T.listcode(b)
+ for i = 1, table.getn(a) do
+ a[i] = string.gsub(a[i], '%b()', '') -- remove line number
+ b[i] = string.gsub(b[i], '%b()', '') -- remove line number
+ assert(a[i] == b[i])
+ end
+end
+
+
+-- some basic instructions
+check(function ()
+ (function () end){f()}
+end, 'CLOSURE', 'NEWTABLE', 'GETGLOBAL', 'CALL', 'SETLIST', 'CALL', 'RETURN')
+
+
+-- sequence of LOADNILs
+check(function ()
+ local a,b,c
+ local d; local e;
+ a = nil; d=nil
+end, 'RETURN')
+
+
+-- single return
+check (function (a,b,c) return a end, 'RETURN')
+
+
+-- infinite loops
+check(function () while true do local a = -1 end end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () while 1 do local a = -1 end end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () repeat local x = 1 until false end,
+'LOADK', 'JMP', 'RETURN')
+
+check(function () repeat local x until nil end,
+'LOADNIL', 'JMP', 'RETURN')
+
+check(function () repeat local x = 1 until true end,
+'LOADK', 'RETURN')
+
+
+-- concat optimization
+check(function (a,b,c,d) return a..b..c..d end,
+ 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
+
+-- not
+check(function () return not not nil end, 'LOADBOOL', 'RETURN')
+check(function () return not not false end, 'LOADBOOL', 'RETURN')
+check(function () return not not true end, 'LOADBOOL', 'RETURN')
+check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
+
+-- direct access to locals
+check(function ()
+ local a,b,c,d
+ a = b*2
+ c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b
+end,
+ 'MUL',
+ 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
+ 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
+
+
+-- direct access to constants
+check(function ()
+ local a,b
+ a.x = 0
+ a.x = b
+ a[b] = 'y'
+ a = 1 - a
+ b = 1/a
+ b = 5+4
+ a[true] = false
+end,
+ 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK',
+ 'SETTABLE', 'RETURN')
+
+local function f () return -((2^8 + -(-1)) % 8)/2 * 4 - 3 end
+
+check(f, 'LOADK', 'RETURN')
+assert(f() == -5)
+
+check(function ()
+ local a,b,c
+ b[c], a = c, b
+ b[a], a = c, b
+ a, b = c, a
+ a = a
+end,
+ 'MOVE', 'MOVE', 'SETTABLE',
+ 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
+ 'MOVE', 'MOVE', 'MOVE',
+ -- no code for a = a
+ 'RETURN')
+
+
+-- x == nil , x ~= nil
+checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
+ function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
+
+check(function () if a==nil then a=1 end end,
+'GETGLOBAL', 'EQ', 'JMP', 'LOADK', 'SETGLOBAL', 'RETURN')
+
+-- de morgan
+checkequal(function () local a; if not (a or b) then b=a end end,
+ function () local a; if (not a and not b) then b=a end end)
+
+checkequal(function (l) local a; return 0 <= a and a <= l end,
+ function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
+
+
+print 'OK'
+
diff --git a/test/PUC-Lua-5.1-tests/constructs.lua b/test/PUC-Lua-5.1-tests/constructs.lua
new file mode 100644
index 0000000..5fb3798
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/constructs.lua
@@ -0,0 +1,240 @@
+print "testing syntax"
+
+-- testing priorities
+
+assert(2^3^2 == 2^(3^2));
+assert(2^3*4 == (2^3)*4);
+assert(2^-2 == 1/4 and -2^- -2 == - - -4);
+assert(not nil and 2 and not(2>3 or 3<2));
+assert(-3-1-5 == 0+0-9);
+assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0);
+assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33");
+assert(not(2+1 > 3*1) and "a".."b" > "a");
+
+assert(not ((true or false) and nil))
+assert( true or false and nil)
+
+local a,b = 1,nil;
+assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
+x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
+x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
+
+x,y=1,2;
+assert((x>y) and x or y == 2);
+x,y=2,1;
+assert((x>y) and x or y == 2);
+
+assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
+
+
+-- silly loops
+repeat until 1; repeat until true;
+while false do end; while nil do end;
+
+do -- test old bug (first name could not be an `upvalue')
+ local a; function f(x) x={a=1}; x={x=1}; x={G=1} end
+end
+
+function f (i)
+ if type(i) ~= 'number' then return i,'jojo'; end;
+ if i > 0 then return i, f(i-1); end;
+end
+
+x = {f(3), f(5), f(10);};
+assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
+assert(x[nil] == nil)
+x = {f'alo', f'xixi', nil};
+assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
+x = {f'alo'..'xixi'};
+assert(x[1] == 'aloxixi')
+x = {f{}}
+assert(x[2] == 'jojo' and type(x[1]) == 'table')
+
+
+local f = function (i)
+ if i < 10 then return 'a';
+ elseif i < 20 then return 'b';
+ elseif i < 30 then return 'c';
+ end;
+end
+
+assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
+
+for i=1,1000 do break; end;
+n=100;
+i=3;
+t = {};
+a=nil
+while not a do
+ a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
+end
+assert(a == n*(n+1)/2 and i==3);
+assert(t[1] and t[n] and not t[0] and not t[n+1])
+
+function f(b)
+ local x = 1;
+ repeat
+ local a;
+ if b==1 then local b=1; x=10; break
+ elseif b==2 then x=20; break;
+ elseif b==3 then x=30;
+ else local a,b,c,d=math.sin(1); x=x+1;
+ end
+ until x>=12;
+ return x;
+end;
+
+assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
+
+
+local f = function (i)
+ if i < 10 then return 'a'
+ elseif i < 20 then return 'b'
+ elseif i < 30 then return 'c'
+ else return 8
+ end
+end
+
+assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
+
+local a, b = nil, 23
+x = {f(100)*2+3 or a, a or b+2}
+assert(x[1] == 19 and x[2] == 25)
+x = {f=2+3 or a, a = b+2}
+assert(x.f == 5 and x.a == 25)
+
+a={y=1}
+x = {a.y}
+assert(x[1] == 1)
+
+function f(i)
+ while 1 do
+ if i>0 then i=i-1;
+ else return; end;
+ end;
+end;
+
+function g(i)
+ while 1 do
+ if i>0 then i=i-1
+ else return end
+ end
+end
+
+f(10); g(10);
+
+do
+ function f () return 1,2,3; end
+ local a, b, c = f();
+ assert(a==1 and b==2 and c==3)
+ a, b, c = (f());
+ assert(a==1 and b==nil and c==nil)
+end
+
+local a,b = 3 and f();
+assert(a==1 and b==nil)
+
+function g() f(); return; end;
+assert(g() == nil)
+function g() return nil or f() end
+a,b = g()
+assert(a==1 and b==nil)
+
+print'+';
+
+
+f = [[
+return function ( a , b , c , d , e )
+ local x = a >= b or c or ( d and e ) or nil
+ return x
+end , { a = 1 , b = 2 >= 1 , } or { 1 };
+]]
+f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes
+f,a = loadstring(f)();
+assert(a.a == 1 and a.b)
+
+function g (a,b,c,d,e)
+ if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
+end
+
+function h (a,b,c,d,e)
+ while (a>=b or c or (d and e) or nil) do return 1; end;
+ return 0;
+end;
+
+assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
+assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
+assert(f(1,2,'a')
+~= -- force SETLINE before nil
+nil, "")
+assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
+assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
+ h(1,2,nil,1,'x') == 1)
+assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
+ h(1,2,nil,nil,'x') == 0)
+assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
+ h(1,2,nil,1,nil) == 0)
+
+assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
+x = 2<3 and not 3; assert(x==false)
+x = 2<1 or (2>1 and 'a'); assert(x=='a')
+
+
+do
+ local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2
+ assert(a==2)
+end
+
+function F(a)
+ assert(debug.getinfo(1, "n").name == 'F')
+ return a,2,3
+end
+
+a,b = F(1)~=nil; assert(a == true and b == nil);
+a,b = F(nil)==nil; assert(a == true and b == nil)
+
+----------------------------------------------------------------
+-- creates all combinations of
+-- [not] ([not] arg op [not] (arg op [not] arg ))
+-- and tests each one
+
+function ID(x) return x end
+
+function f(t, i)
+ local b = t.n
+ local res = math.mod(math.floor(i/c), b)+1
+ c = c*b
+ return t[res]
+end
+
+local arg = {" ( 1 < 2 ) ", " ( 1 >= 2 ) ", " F ( ) ", " nil "; n=4}
+
+local op = {" and ", " or ", " == ", " ~= "; n=4}
+
+local neg = {" ", " not "; n=2}
+
+local i = 0
+repeat
+ c = 1
+ local s = f(neg, i)..'ID('..f(neg, i)..f(arg, i)..f(op, i)..
+ f(neg, i)..'ID('..f(arg, i)..f(op, i)..f(neg, i)..f(arg, i)..'))'
+ local s1 = string.gsub(s, 'ID', '')
+ K,X,NX,WX1,WX2 = nil
+ s = string.format([[
+ local a = %s
+ local b = not %s
+ K = b
+ local xxx;
+ if %s then X = a else X = b end
+ if %s then NX = b else NX = a end
+ while %s do WX1 = a; break end
+ while %s do WX2 = a; break end
+ repeat if (%s) then break end; assert(b) until not(%s)
+ ]], s1, s, s1, s, s1, s, s1, s, s)
+ assert(loadstring(s))()
+ assert(X and not NX and not WX1 == K and not WX2 == K)
+ if math.mod(i,4000) == 0 then print('+') end
+ i = i+1
+until i==c
+
+print'OK'
diff --git a/test/PUC-Lua-5.1-tests/db.lua b/test/PUC-Lua-5.1-tests/db.lua
new file mode 100644
index 0000000..9d2c86f
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/db.lua
@@ -0,0 +1,499 @@
+-- testing debug library
+
+local function dostring(s) return assert(loadstring(s))() end
+
+print"testing debug library and debug information"
+
+do
+local a=1
+end
+
+function test (s, l, p)
+ collectgarbage() -- avoid gc during trace
+ local function f (event, line)
+ assert(event == 'line')
+ local l = table.remove(l, 1)
+ if p then print(l, line) end
+ assert(l == line, "wrong trace!!")
+ end
+ debug.sethook(f,"l"); loadstring(s)(); debug.sethook()
+ assert(table.getn(l) == 0)
+end
+
+
+do
+ local a = debug.getinfo(print)
+ assert(a.what == "C" and a.short_src == "[C]")
+ local b = debug.getinfo(test, "SfL")
+ assert(b.name == nil and b.what == "Lua" and b.linedefined == 11 and
+ b.lastlinedefined == b.linedefined + 10 and
+ b.func == test and not string.find(b.short_src, "%["))
+ assert(b.activelines[b.linedefined + 1] and
+ b.activelines[b.lastlinedefined])
+ assert(not b.activelines[b.linedefined] and
+ not b.activelines[b.lastlinedefined + 1])
+end
+
+
+-- test file and string names truncation
+a = "function f () end"
+local function dostring (s, x) return loadstring(s, x)() end
+dostring(a)
+assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
+dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
+assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
+dostring("\n"..a)
+assert(debug.getinfo(f).short_src == '[string "..."]')
+dostring(a, "")
+assert(debug.getinfo(f).short_src == '[string ""]')
+dostring(a, "@xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, "@"..string.rep('p', 1000)..'t')
+assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
+dostring(a, "=xuxu")
+assert(debug.getinfo(f).short_src == "xuxu")
+dostring(a, string.format("=%s", string.rep('x', 500)))
+assert(string.find(debug.getinfo(f).short_src, "^x*"))
+dostring(a, "=")
+assert(debug.getinfo(f).short_src == "")
+a = nil; f = nil;
+
+
+repeat
+ local g = {x = function ()
+ local a = debug.getinfo(2)
+ assert(a.name == 'f' and a.namewhat == 'local')
+ a = debug.getinfo(1)
+ assert(a.name == 'x' and a.namewhat == 'field')
+ return 'xixi'
+ end}
+ local f = function () return 1+1 and (not 1 or g.x()) end
+ assert(f() == 'xixi')
+ g = debug.getinfo(f)
+ assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
+
+ function f (x, name) -- local!
+ name = name or 'f'
+ local a = debug.getinfo(1)
+ assert(a.name == name and a.namewhat == 'local')
+ return x
+ end
+
+ -- breaks in different conditions
+ if 3>4 then break end; f()
+ if 3<4 then a=1 else break end; f()
+ while 1 do local x=10; break end; f()
+ local b = 1
+ if 3>4 then return math.sin(1) end; f()
+ a = 3<4; f()
+ a = 3<4 or 1; f()
+ repeat local x=20; if 4>3 then f() else break end; f() until 1
+ g = {}
+ f(g).x = f(2) and f(10)+f(9)
+ assert(g.x == f(19))
+ function g(x) if not x then return 3 end return (x('a', 'x')) end
+ assert(g(f) == 'a')
+until 1
+
+test([[if
+math.sin(1)
+then
+ a=1
+else
+ a=2
+end
+]], {2,4,7})
+
+test([[--
+if nil then
+ a=1
+else
+ a=2
+end
+]], {2,5,6})
+
+test([[a=1
+repeat
+ a=a+1
+until a==3
+]], {1,3,4,3,4})
+
+test([[ do
+ return
+end
+]], {2})
+
+test([[local a
+a=1
+while a<=3 do
+ a=a+1
+end
+]], {2,3,4,3,4,3,4,3,5})
+
+test([[while math.sin(1) do
+ if math.sin(1)
+ then
+ break
+ end
+end
+a=1]], {1,2,4,7})
+
+test([[for i=1,3 do
+ a=i
+end
+]], {1,2,1,2,1,2,1,3})
+
+test([[for i,v in pairs{'a','b'} do
+ a=i..v
+end
+]], {1,2,1,2,1,3})
+
+test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
+
+
+
+print'+'
+
+a = {}; L = nil
+local glob = 1
+local oldglob = glob
+debug.sethook(function (e,l)
+ collectgarbage() -- force GC during a hook
+ local f, m, c = debug.gethook()
+ assert(m == 'crl' and c == 0)
+ if e == "line" then
+ if glob ~= oldglob then
+ L = l-1 -- get the first line where "glob" has changed
+ oldglob = glob
+ end
+ elseif e == "call" then
+ local f = debug.getinfo(2, "f").func
+ a[f] = 1
+ else assert(e == "return")
+ end
+end, "crl")
+
+function f(a,b)
+ collectgarbage()
+ local _, x = debug.getlocal(1, 1)
+ local _, y = debug.getlocal(1, 2)
+ assert(x == a and y == b)
+ assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
+ assert(debug.setlocal(2, 4, "maçã") == "B")
+ x = debug.getinfo(2)
+ assert(x.func == g and x.what == "Lua" and x.name == 'g' and
+ x.nups == 0 and string.find(x.source, "^@.*db%.lua"))
+ glob = glob+1
+ assert(debug.getinfo(1, "l").currentline == L+1)
+ assert(debug.getinfo(1, "l").currentline == L+2)
+end
+
+function foo()
+ glob = glob+1
+ assert(debug.getinfo(1, "l").currentline == L+1)
+end; foo() -- set L
+-- check line counting inside strings and empty lines
+
+_ = 'alo\
+alo' .. [[
+
+]]
+--[[
+]]
+assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
+
+
+function g(...)
+ do local a,b,c; a=math.sin(40); end
+ local feijao
+ local AAAA,B = "xuxu", "mamão"
+ f(AAAA,B)
+ assert(AAAA == "pera" and B == "maçã")
+ do
+ local B = 13
+ local x,y = debug.getlocal(1,5)
+ assert(x == 'B' and y == 13)
+ end
+end
+
+g()
+
+
+assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
+
+
+-- tests for manipulating non-registered locals (C and Lua temporaries)
+
+local n, v = debug.getlocal(0, 1)
+assert(v == 0 and n == "(*temporary)")
+local n, v = debug.getlocal(0, 2)
+assert(v == 2 and n == "(*temporary)")
+assert(not debug.getlocal(0, 3))
+assert(not debug.getlocal(0, 0))
+
+function f()
+ assert(select(2, debug.getlocal(2,3)) == 1)
+ assert(not debug.getlocal(2,4))
+ debug.setlocal(2, 3, 10)
+ return 20
+end
+
+function g(a,b) return (a+1) + f() end
+
+assert(g(0,0) == 30)
+
+
+debug.sethook(nil);
+assert(debug.gethook() == nil)
+
+
+-- testing access to function arguments
+
+X = nil
+a = {}
+function a:f (a, b, ...) local c = 13 end
+debug.sethook(function (e)
+ assert(e == "call")
+ dostring("XX = 12") -- test dostring inside hooks
+ -- testing errors inside hooks
+ assert(not pcall(loadstring("a='joao'+1")))
+ debug.sethook(function (e, l)
+ assert(debug.getinfo(2, "l").currentline == l)
+ local f,m,c = debug.gethook()
+ assert(e == "line")
+ assert(m == 'l' and c == 0)
+ debug.sethook(nil) -- hook is called only once
+ assert(not X) -- check that
+ X = {}; local i = 1
+ local x,y
+ while 1 do
+ x,y = debug.getlocal(2, i)
+ if x==nil then break end
+ X[x] = y
+ i = i+1
+ end
+ end, "l")
+end, "c")
+
+a:f(1,2,3,4,5)
+assert(X.self == a and X.a == 1 and X.b == 2 and X.arg.n == 3 and X.c == nil)
+assert(XX == 12)
+assert(debug.gethook() == nil)
+
+
+-- testing upvalue access
+local function getupvalues (f)
+ local t = {}
+ local i = 1
+ while true do
+ local name, value = debug.getupvalue(f, i)
+ if not name then break end
+ assert(not t[name])
+ t[name] = value
+ i = i + 1
+ end
+ return t
+end
+
+local a,b,c = 1,2,3
+local function foo1 (a) b = a; return c end
+local function foo2 (x) a = x; return c+b end
+assert(debug.getupvalue(foo1, 3) == nil)
+assert(debug.getupvalue(foo1, 0) == nil)
+assert(debug.setupvalue(foo1, 3, "xuxu") == nil)
+local t = getupvalues(foo1)
+assert(t.a == nil and t.b == 2 and t.c == 3)
+t = getupvalues(foo2)
+assert(t.a == 1 and t.b == 2 and t.c == 3)
+assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
+assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
+-- cannot manipulate C upvalues from Lua
+assert(debug.getupvalue(io.read, 1) == nil)
+assert(debug.setupvalue(io.read, 1, 10) == nil)
+
+
+-- testing count hooks
+local a=0
+debug.sethook(function (e) a=a+1 end, "", 1)
+a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
+debug.sethook(function (e) a=a+1 end, "", 4)
+a=0; for i=1,1000 do end; assert(250 < a and a < 255)
+local f,m,c = debug.gethook()
+assert(m == "" and c == 4)
+debug.sethook(function (e) a=a+1 end, "", 4000)
+a=0; for i=1,1000 do end; assert(a == 0)
+debug.sethook(print, "", 2^24 - 1) -- count upperbound
+local f,m,c = debug.gethook()
+assert(({debug.gethook()})[3] == 2^24 - 1)
+debug.sethook()
+
+
+-- tests for tail calls
+local function f (x)
+ if x then
+ assert(debug.getinfo(1, "S").what == "Lua")
+ local tail = debug.getinfo(2)
+ assert(not pcall(getfenv, 3))
+ assert(tail.what == "tail" and tail.short_src == "(tail call)" and
+ tail.linedefined == -1 and tail.func == nil)
+ assert(debug.getinfo(3, "f").func == g1)
+ assert(getfenv(3))
+ assert(debug.getinfo(4, "S").what == "tail")
+ assert(not pcall(getfenv, 5))
+ assert(debug.getinfo(5, "S").what == "main")
+ assert(getfenv(5))
+ print"+"
+ end
+end
+
+function g(x) return f(x) end
+
+function g1(x) g(x) end
+
+local function h (x) local f=g1; return f(x) end
+
+h(true)
+
+local b = {}
+debug.sethook(function (e) table.insert(b, e) end, "cr")
+h(false)
+debug.sethook()
+local res = {"return", -- first return (from sethook)
+ "call", "call", "call", "call",
+ "return", "tail return", "return", "tail return",
+ "call", -- last call (to sethook)
+}
+for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
+
+
+lim = 30000
+local function foo (x)
+ if x==0 then
+ assert(debug.getinfo(lim+2).what == "main")
+ for i=2,lim do assert(debug.getinfo(i, "S").what == "tail") end
+ else return foo(x-1)
+ end
+end
+
+foo(lim)
+
+
+print"+"
+
+
+-- testing traceback
+
+assert(debug.traceback(print) == print)
+assert(debug.traceback(print, 4) == print)
+assert(string.find(debug.traceback("hi", 4), "^hi\n"))
+assert(string.find(debug.traceback("hi"), "^hi\n"))
+assert(not string.find(debug.traceback("hi"), "'traceback'"))
+assert(string.find(debug.traceback("hi", 0), "'traceback'"))
+assert(string.find(debug.traceback(), "^stack traceback:\n"))
+
+-- testing debugging of coroutines
+
+local function checktraceback (co, p)
+ local tb = debug.traceback(co)
+ local i = 0
+ for l in string.gmatch(tb, "[^\n]+\n?") do
+ assert(i == 0 or string.find(l, p[i]))
+ i = i+1
+ end
+ assert(p[i] == nil)
+end
+
+
+local function f (n)
+ if n > 0 then return f(n-1)
+ else coroutine.yield() end
+end
+
+local co = coroutine.create(f)
+coroutine.resume(co, 3)
+checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
+
+
+co = coroutine.create(function (x)
+ local a = 1
+ coroutine.yield(debug.getinfo(1, "l"))
+ coroutine.yield(debug.getinfo(1, "l").currentline)
+ return a
+ end)
+
+local tr = {}
+local foo = function (e, l) table.insert(tr, l) end
+debug.sethook(co, foo, "l")
+
+local _, l = coroutine.resume(co, 10)
+local x = debug.getinfo(co, 1, "lfLS")
+assert(x.currentline == l.currentline and x.activelines[x.currentline])
+assert(type(x.func) == "function")
+for i=x.linedefined + 1, x.lastlinedefined do
+ assert(x.activelines[i])
+ x.activelines[i] = nil
+end
+assert(next(x.activelines) == nil) -- no 'extra' elements
+assert(debug.getinfo(co, 2) == nil)
+local a,b = debug.getlocal(co, 1, 1)
+assert(a == "x" and b == 10)
+a,b = debug.getlocal(co, 1, 2)
+assert(a == "a" and b == 1)
+debug.setlocal(co, 1, 2, "hi")
+assert(debug.gethook(co) == foo)
+assert(table.getn(tr) == 2 and
+ tr[1] == l.currentline-1 and tr[2] == l.currentline)
+
+a,b,c = pcall(coroutine.resume, co)
+assert(a and b and c == l.currentline+1)
+checktraceback(co, {"yield", "in function <"})
+
+a,b = coroutine.resume(co)
+assert(a and b == "hi")
+assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
+assert(debug.gethook(co) == foo)
+assert(debug.gethook() == nil)
+checktraceback(co, {})
+
+
+-- check traceback of suspended (or dead with error) coroutines
+
+function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
+
+co = coroutine.create(function (x) f(x) end)
+a, b = coroutine.resume(co, 3)
+t = {"'yield'", "'f'", "in function <"}
+while coroutine.status(co) == "suspended" do
+ checktraceback(co, t)
+ a, b = coroutine.resume(co)
+ table.insert(t, 2, "'f'") -- one more recursive call to 'f'
+end
+t[1] = "'error'"
+checktraceback(co, t)
+
+
+-- test acessing line numbers of a coroutine from a resume inside
+-- a C function (this is a known bug in Lua 5.0)
+
+local function g(x)
+ coroutine.yield(x)
+end
+
+local function f (i)
+ debug.sethook(function () end, "l")
+ for j=1,1000 do
+ g(i+j)
+ end
+end
+
+local co = coroutine.wrap(f)
+co(10)
+pcall(co)
+pcall(co)
+
+
+assert(type(debug.getregistry()) == "table")
+
+
+print"OK"
+
diff --git a/test/PUC-Lua-5.1-tests/errors.lua b/test/PUC-Lua-5.1-tests/errors.lua
new file mode 100644
index 0000000..e881211
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/errors.lua
@@ -0,0 +1,250 @@
+print("testing errors")
+
+function doit (s)
+ local f, msg = loadstring(s)
+ if f == nil then return msg end
+ local cond, msg = pcall(f)
+ return (not cond) and msg
+end
+
+
+function checkmessage (prog, msg)
+ assert(string.find(doit(prog), msg, 1, true))
+end
+
+function checksyntax (prog, extra, token, line)
+ local msg = doit(prog)
+ token = string.gsub(token, "(%p)", "%%%1")
+ local pt = string.format([[^%%[string ".*"%%]:%d: .- near '%s'$]],
+ line, token)
+ assert(string.find(msg, pt))
+ assert(string.find(msg, msg, 1, true))
+end
+
+
+-- test error message with no extra info
+assert(doit("error('hi', 0)") == 'hi')
+
+-- test error message with no info
+assert(doit("error()") == nil)
+
+
+-- test common errors/errors that crashed in the past
+assert(doit("unpack({}, 1, n=2^30)"))
+assert(doit("a=math.sin()"))
+assert(not doit("tostring(1)") and doit("tostring()"))
+assert(doit"tonumber()")
+assert(doit"repeat until 1; a")
+checksyntax("break label", "", "label", 1)
+assert(doit";")
+assert(doit"a=1;;")
+assert(doit"return;;")
+assert(doit"assert(false)")
+assert(doit"assert(nil)")
+assert(doit"a=math.sin\n(3)")
+assert(doit("function a (... , ...) end"))
+assert(doit("function a (, ...) end"))
+
+checksyntax([[
+ local a = {4
+
+]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
+
+
+-- tests for better error messages
+
+checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
+checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
+ "local 'bbbb'")
+checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
+checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
+assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
+checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
+
+aaa = nil
+checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
+checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
+checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
+checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'")
+assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
+
+checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
+checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
+checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
+checkmessage("aaa={}; x=-aaa", "global 'aaa'")
+assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
+assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
+
+checkmessage([[aaa=9
+repeat until 3==3
+local x=math.sin(math.cos(3))
+if math.sin(1) == x then return math.sin(1) end -- tail call
+local a,b = 1, {
+ {x='a'..'b'..'c', y='b', z=x},
+ {1,2,3,4,5} or 3+3<=3+3,
+ 3+1>3+1,
+ {d = x and aaa[x or y]}}
+]], "global 'aaa'")
+
+checkmessage([[
+local x,y = {},1
+if math.sin(1) == 0 then return 3 end -- return
+x.a()]], "field 'a'")
+
+checkmessage([[
+prefix = nil
+insert = nil
+while 1 do
+ local a
+ if nil then break end
+ insert(prefix, a)
+end]], "global 'insert'")
+
+checkmessage([[ -- tail call
+ return math.sin("a")
+]], "'sin'")
+
+checkmessage([[collectgarbage("nooption")]], "invalid option")
+
+checkmessage([[x = print .. "a"]], "concatenate")
+
+checkmessage("getmetatable(io.stdin).__gc()", "no value")
+
+print'+'
+
+
+-- testing line error
+
+function lineerror (s)
+ local err,msg = pcall(loadstring(s))
+ local line = string.match(msg, ":(%d+):")
+ return line and line+0
+end
+
+assert(lineerror"local a\n for i=1,'a' do \n print(i) \n end" == 2)
+assert(lineerror"\n local a \n for k,v in 3 \n do \n print(k) \n end" == 3)
+assert(lineerror"\n\n for k,v in \n 3 \n do \n print(k) \n end" == 4)
+assert(lineerror"function a.x.y ()\na=a+1\nend" == 1)
+
+local p = [[
+function g() f() end
+function f(x) error('a', X) end
+g()
+]]
+X=3;assert(lineerror(p) == 3)
+X=0;assert(lineerror(p) == nil)
+X=1;assert(lineerror(p) == 2)
+X=2;assert(lineerror(p) == 1)
+
+lineerror = nil
+
+C = 0
+local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
+
+local function checkstackmessage (m)
+ return (string.find(m, "^.-:%d+: stack overflow"))
+end
+assert(checkstackmessage(doit('y()')))
+assert(checkstackmessage(doit('y()')))
+assert(checkstackmessage(doit('y()')))
+-- teste de linhas em erro
+C = 0
+local l1
+local function g()
+ l1 = debug.getinfo(1, "l").currentline; y()
+end
+local _, stackmsg = xpcall(g, debug.traceback)
+local stack = {}
+for line in string.gmatch(stackmsg, "[^\n]*") do
+ local curr = string.match(line, ":(%d+):")
+ if curr then table.insert(stack, tonumber(curr)) end
+end
+local i=1
+while stack[i] ~= l1 do
+ assert(stack[i] == l)
+ i = i+1
+end
+assert(i > 15)
+
+
+-- error in error handling
+local res, msg = xpcall(error, error)
+assert(not res and type(msg) == 'string')
+
+local function f (x)
+ if x==0 then error('a\n')
+ else
+ local aux = function () return f(x-1) end
+ local a,b = xpcall(aux, aux)
+ return a,b
+ end
+end
+f(3)
+
+-- non string messages
+function f() error{msg='x'} end
+res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
+assert(msg.msg == 'xy')
+
+print('+')
+checksyntax("syntax error", "", "error", 1)
+checksyntax("1.000", "", "1.000", 1)
+checksyntax("[[a]]", "", "[[a]]", 1)
+checksyntax("'aa'", "", "'aa'", 1)
+
+-- test 255 as first char in a chunk
+checksyntax("\255a = 1", "", "\255", 1)
+
+doit('I = loadstring("a=9+"); a=3')
+assert(a==3 and I == nil)
+print('+')
+
+lim = 1000
+if rawget(_G, "_soft") then lim = 100 end
+for i=1,lim do
+ doit('a = ')
+ doit('a = 4+nil')
+end
+
+
+-- testing syntax limits
+local function testrep (init, rep)
+ local s = "local a; "..init .. string.rep(rep, 400)
+ local a,b = loadstring(s)
+ assert(not a and string.find(b, "syntax levels"))
+end
+testrep("a=", "{")
+testrep("a=", "(")
+testrep("", "a(")
+testrep("", "do ")
+testrep("", "while a do ")
+testrep("", "if a then else ")
+testrep("", "function foo () ")
+testrep("a=", "a..")
+testrep("a=", "a^")
+
+
+-- testing other limits
+-- upvalues
+local s = "function foo ()\n local "
+for j = 1,70 do
+ s = s.."a"..j..", "
+end
+s = s.."b\n"
+for j = 1,70 do
+ s = s.."function foo"..j.." ()\n a"..j.."=3\n"
+end
+local a,b = loadstring(s)
+assert(string.find(b, "line 3"))
+
+-- local variables
+s = "\nfunction foo ()\n local "
+for j = 1,300 do
+ s = s.."a"..j..", "
+end
+s = s.."b\n"
+local a,b = loadstring(s)
+assert(string.find(b, "line 2"))
+
+
+print('OK')
diff --git a/test/PUC-Lua-5.1-tests/etc/ltests.c b/test/PUC-Lua-5.1-tests/etc/ltests.c
new file mode 100644
index 0000000..be949e5
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/etc/ltests.c
@@ -0,0 +1,1147 @@
+/*
+** $Id: ltests.c,v 2.36 2006/01/10 13:13:06 roberto Exp $
+** Internal Module for Debugging of the Lua Implementation
+** See Copyright Notice in lua.h
+*/
+
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ltests_c
+#define LUA_CORE
+
+#include "lua.h"
+
+#include "lapi.h"
+#include "lauxlib.h"
+#include "lcode.h"
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lopcodes.h"
+#include "lstate.h"
+#include "lstring.h"
+#include "ltable.h"
+#include "lualib.h"
+
+
+
+/*
+** The whole module only makes sense with LUA_DEBUG on
+*/
+#if defined(LUA_DEBUG)
+
+
+int Trick = 0;
+
+
+static lua_State *lua_state = NULL;
+
+int islocked = 0;
+
+
+#define obj_at(L,k) (L->ci->base+(k) - 1)
+
+
+static void setnameval (lua_State *L, const char *name, int val) {
+ lua_pushstring(L, name);
+ lua_pushinteger(L, val);
+ lua_settable(L, -3);
+}
+
+
+/*
+** {======================================================================
+** Controlled version for realloc.
+** =======================================================================
+*/
+
+#define MARK 0x55 /* 01010101 (a nice pattern) */
+
+#ifndef EXTERNMEMCHECK
+/* full memory check */
+#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
+#define MARKSIZE 16 /* size of marks after each block */
+#define blockhead(b) (cast(char *, b) - HEADER)
+#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
+#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
+#define fillmem(mem,size) memset(mem, -MARK, size)
+#else
+/* external memory check: don't do it twice */
+#define HEADER 0
+#define MARKSIZE 0
+#define blockhead(b) (b)
+#define setsize(newblock, size) /* empty */
+#define checkblocksize(b,size) (1)
+#define fillmem(mem,size) /* empty */
+#endif
+
+
+Memcontrol memcontrol = {0L, 0L, 0L, ULONG_MAX};
+
+
+static void *checkblock (void *block, size_t size) {
+ void *b = blockhead(block);
+ int i;
+ for (i=0;i<MARKSIZE;i++)
+ lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
+ return b;
+}
+
+
+static void freeblock (Memcontrol *mc, void *block, size_t size) {
+ if (block) {
+ lua_assert(checkblocksize(block, size));
+ block = checkblock(block, size);
+ fillmem(block, size+HEADER+MARKSIZE); /* erase block */
+ free(block); /* free original block */
+ mc->numblocks--;
+ mc->total -= size;
+ }
+}
+
+
+void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
+ Memcontrol *mc = cast(Memcontrol *, ud);
+ lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
+ if (size == 0) {
+ freeblock(mc, block, oldsize);
+ return NULL;
+ }
+ else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
+ return NULL; /* to test memory allocation errors */
+ else {
+ void *newblock;
+ int i;
+ size_t realsize = HEADER+size+MARKSIZE;
+ size_t commonsize = (oldsize < size) ? oldsize : size;
+ if (realsize < size) return NULL; /* overflow! */
+ newblock = malloc(realsize); /* alloc a new block */
+ if (newblock == NULL) return NULL;
+ if (block) {
+ memcpy(cast(char *, newblock)+HEADER, block, commonsize);
+ freeblock(mc, block, oldsize); /* erase (and check) old copy */
+ }
+ /* initialize new part of the block with something `weird' */
+ fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
+ mc->total += size;
+ if (mc->total > mc->maxmem)
+ mc->maxmem = mc->total;
+ mc->numblocks++;
+ setsize(newblock, size);
+ for (i=0;i<MARKSIZE;i++)
+ *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
+ return cast(char *, newblock)+HEADER;
+ }
+}
+
+
+/* }====================================================================== */
+
+
+
+/*
+** {======================================================
+** Functions to check memory consistency
+** =======================================================
+*/
+
+static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
+ if (isdead(g,t)) return 0;
+ if (g->gcstate == GCSpropagate)
+ return !isblack(f) || !iswhite(t);
+ else if (g->gcstate == GCSfinalize)
+ return iswhite(f);
+ else
+ return 1;
+}
+
+
+static void printobj (global_State *g, GCObject *o) {
+ int i = 0;
+ GCObject *p;
+ for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++;
+ if (p == NULL) i = -1;
+ printf("%d:%s(%p)-%c(%02X)", i, luaT_typenames[o->gch.tt], (void *)o,
+ isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->gch.marked);
+}
+
+
+static int testobjref (global_State *g, GCObject *f, GCObject *t) {
+ int r = testobjref1(g,f,t);
+ if (!r) {
+ printf("%d(%02X) - ", g->gcstate, g->currentwhite);
+ printobj(g, f);
+ printf("\t-> ");
+ printobj(g, t);
+ printf("\n");
+ }
+ return r;
+}
+
+#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
+
+#define checkvalref(g,f,t) lua_assert(!iscollectable(t) || \
+ ((ttype(t) == (t)->value.gc->gch.tt) && testobjref(g,f,gcvalue(t))))
+
+
+
+static void checktable (global_State *g, Table *h) {
+ int i;
+ int weakkey = 0;
+ int weakvalue = 0;
+ const TValue *mode;
+ GCObject *hgc = obj2gco(h);
+ if (h->metatable)
+ checkobjref(g, hgc, h->metatable);
+ mode = gfasttm(g, h->metatable, TM_MODE);
+ if (mode && ttisstring(mode)) { /* is there a weak mode? */
+ weakkey = (strchr(svalue(mode), 'k') != NULL);
+ weakvalue = (strchr(svalue(mode), 'v') != NULL);
+ }
+ i = h->sizearray;
+ while (i--)
+ checkvalref(g, hgc, &h->array[i]);
+ i = sizenode(h);
+ while (i--) {
+ Node *n = gnode(h, i);
+ if (!ttisnil(gval(n))) {
+ lua_assert(!ttisnil(gkey(n)));
+ checkvalref(g, hgc, gkey(n));
+ checkvalref(g, hgc, gval(n));
+ }
+ }
+}
+
+
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void checkproto (global_State *g, Proto *f) {
+ int i;
+ GCObject *fgc = obj2gco(f);
+ if (f->source) checkobjref(g, fgc, f->source);
+ for (i=0; i<f->sizek; i++) {
+ if (ttisstring(f->k+i))
+ checkobjref(g, fgc, rawtsvalue(f->k+i));
+ }
+ for (i=0; i<f->sizeupvalues; i++) {
+ if (f->upvalues[i])
+ checkobjref(g, fgc, f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) {
+ if (f->p[i])
+ checkobjref(g, fgc, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) {
+ if (f->locvars[i].varname)
+ checkobjref(g, fgc, f->locvars[i].varname);
+ }
+}
+
+
+
+static void checkclosure (global_State *g, Closure *cl) {
+ GCObject *clgc = obj2gco(cl);
+ checkobjref(g, clgc, cl->l.env);
+ if (cl->c.isC) {
+ int i;
+ for (i=0; i<cl->c.nupvalues; i++)
+ checkvalref(g, clgc, &cl->c.upvalue[i]);
+ }
+ else {
+ int i;
+ lua_assert(cl->l.nupvalues == cl->l.p->nups);
+ checkobjref(g, clgc, cl->l.p);
+ for (i=0; i<cl->l.nupvalues; i++) {
+ if (cl->l.upvals[i]) {
+ lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL);
+ checkobjref(g, clgc, cl->l.upvals[i]);
+ }
+ }
+ }
+}
+
+
+static void checkstack (global_State *g, lua_State *L1) {
+ StkId o;
+ CallInfo *ci;
+ GCObject *uvo;
+ lua_assert(!isdead(g, obj2gco(L1)));
+ for (uvo = L1->openupval; uvo != NULL; uvo = uvo->gch.next) {
+ UpVal *uv = gco2uv(uvo);
+ lua_assert(uv->v != &uv->u.value); /* must be open */
+ lua_assert(!isblack(uvo)); /* open upvalues cannot be black */
+ }
+ checkliveness(g, gt(L1));
+ if (L1->base_ci) {
+ for (ci = L1->base_ci; ci <= L1->ci; ci++) {
+ lua_assert(ci->top <= L1->stack_last);
+ lua_assert(lua_checkpc(L1, ci));
+ }
+ }
+ else lua_assert(L1->size_ci == 0);
+ if (L1->stack) {
+ for (o = L1->stack; o < L1->top; o++)
+ checkliveness(g, o);
+ }
+ else lua_assert(L1->stacksize == 0);
+}
+
+
+static void checkobject (global_State *g, GCObject *o) {
+ if (isdead(g, o))
+/* lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);*/
+{ if (!(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep))
+printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marked);
+}
+ else {
+ if (g->gcstate == GCSfinalize)
+ lua_assert(iswhite(o));
+ switch (o->gch.tt) {
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ lua_assert(uv->v == &uv->u.value); /* must be closed */
+ lua_assert(!isgray(o)); /* closed upvalues are never gray */
+ checkvalref(g, o, uv->v);
+ break;
+ }
+ case LUA_TUSERDATA: {
+ Table *mt = gco2u(o)->metatable;
+ if (mt) checkobjref(g, o, mt);
+ break;
+ }
+ case LUA_TTABLE: {
+ checktable(g, gco2h(o));
+ break;
+ }
+ case LUA_TTHREAD: {
+ checkstack(g, gco2th(o));
+ break;
+ }
+ case LUA_TFUNCTION: {
+ checkclosure(g, gco2cl(o));
+ break;
+ }
+ case LUA_TPROTO: {
+ checkproto(g, gco2p(o));
+ break;
+ }
+ default: lua_assert(0);
+ }
+ }
+}
+
+
+int lua_checkpc (lua_State *L, pCallInfo ci) {
+ if (ci == L->base_ci || !f_isLua(ci)) return 1;
+ else {
+ Proto *p = ci_func(ci)->l.p;
+ if (ci < L->ci)
+ return p->code <= ci->savedpc && ci->savedpc <= p->code + p->sizecode;
+ else
+ return p->code <= L->savedpc && L->savedpc <= p->code + p->sizecode;
+ }
+}
+
+
+int lua_checkmemory (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o;
+ UpVal *uv;
+ checkstack(g, g->mainthread);
+ for (o = g->rootgc; o != obj2gco(g->mainthread); o = o->gch.next)
+ checkobject(g, o);
+ for (o = o->gch.next; o != NULL; o = o->gch.next) {
+ lua_assert(o->gch.tt == LUA_TUSERDATA);
+ checkobject(g, o);
+ }
+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+ lua_assert(uv->v != &uv->u.value); /* must be open */
+ lua_assert(!isblack(obj2gco(uv))); /* open upvalues are never black */
+ checkvalref(g, obj2gco(uv), uv->v);
+ }
+ return 0;
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** Disassembler
+** =======================================================
+*/
+
+
+static char *buildop (Proto *p, int pc, char *buff) {
+ Instruction i = p->code[pc];
+ OpCode o = GET_OPCODE(i);
+ const char *name = luaP_opnames[o];
+ int line = getline(p, pc);
+ sprintf(buff, "(%4d) %4d - ", line, pc);
+ switch (getOpMode(o)) {
+ case iABC:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d %4d", name,
+ GETARG_A(i), GETARG_B(i), GETARG_C(i));
+ break;
+ case iABx:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
+ break;
+ case iAsBx:
+ sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
+ break;
+ }
+ return buff;
+}
+
+
+#if 0
+void luaI_printcode (Proto *pt, int size) {
+ int pc;
+ for (pc=0; pc<size; pc++) {
+ char buff[100];
+ printf("%s\n", buildop(pt, pc, buff));
+ }
+ printf("-------\n");
+}
+#endif
+
+
+static int listcode (lua_State *L) {
+ int pc;
+ Proto *p;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ lua_newtable(L);
+ setnameval(L, "maxstack", p->maxstacksize);
+ setnameval(L, "numparams", p->numparams);
+ for (pc=0; pc<p->sizecode; pc++) {
+ char buff[100];
+ lua_pushinteger(L, pc+1);
+ lua_pushstring(L, buildop(p, pc, buff));
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+
+static int listk (lua_State *L) {
+ Proto *p;
+ int i;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ lua_createtable(L, p->sizek, 0);
+ for (i=0; i<p->sizek; i++) {
+ luaA_pushobject(L, p->k+i);
+ lua_rawseti(L, -2, i+1);
+ }
+ return 1;
+}
+
+
+static int listlocals (lua_State *L) {
+ Proto *p;
+ int pc = luaL_checkint(L, 2) - 1;
+ int i = 0;
+ const char *name;
+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
+ 1, "Lua function expected");
+ p = clvalue(obj_at(L, 1))->l.p;
+ while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
+ lua_pushstring(L, name);
+ return i-1;
+}
+
+/* }====================================================== */
+
+
+
+
+static int get_limits (lua_State *L) {
+ lua_createtable(L, 0, 5);
+ setnameval(L, "BITS_INT", LUAI_BITSINT);
+ setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
+ setnameval(L, "MAXVARS", LUAI_MAXVARS);
+ setnameval(L, "MAXSTACK", MAXSTACK);
+ setnameval(L, "MAXUPVALUES", LUAI_MAXUPVALUES);
+ setnameval(L, "NUM_OPCODES", NUM_OPCODES);
+ return 1;
+}
+
+
+static int mem_query (lua_State *L) {
+ if (lua_isnone(L, 1)) {
+ lua_pushinteger(L, memcontrol.total);
+ lua_pushinteger(L, memcontrol.numblocks);
+ lua_pushinteger(L, memcontrol.maxmem);
+ return 3;
+ }
+ else {
+ memcontrol.memlimit = luaL_checkint(L, 1);
+ return 0;
+ }
+}
+
+
+static int settrick (lua_State *L) {
+ Trick = lua_tointeger(L, 1);
+ return 0;
+}
+
+
+/*static int set_gcstate (lua_State *L) {
+ static const char *const state[] = {"propagate", "sweep", "finalize"};
+ return 0;
+}*/
+
+
+static int get_gccolor (lua_State *L) {
+ TValue *o;
+ luaL_checkany(L, 1);
+ o = obj_at(L, 1);
+ if (!iscollectable(o))
+ lua_pushstring(L, "no collectable");
+ else
+ lua_pushstring(L, iswhite(gcvalue(o)) ? "white" :
+ isblack(gcvalue(o)) ? "black" : "grey");
+ return 1;
+}
+
+
+static int gcstate (lua_State *L) {
+ switch(G(L)->gcstate) {
+ case GCSpropagate: lua_pushstring(L, "propagate"); break;
+ case GCSsweepstring: lua_pushstring(L, "sweep strings"); break;
+ case GCSsweep: lua_pushstring(L, "sweep"); break;
+ case GCSfinalize: lua_pushstring(L, "finalize"); break;
+ }
+ return 1;
+}
+
+
+static int hash_query (lua_State *L) {
+ if (lua_isnone(L, 2)) {
+ luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
+ lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash);
+ }
+ else {
+ TValue *o = obj_at(L, 1);
+ Table *t;
+ luaL_checktype(L, 2, LUA_TTABLE);
+ t = hvalue(obj_at(L, 2));
+ lua_pushinteger(L, luaH_mainposition(t, o) - t->node);
+ }
+ return 1;
+}
+
+
+static int stacklevel (lua_State *L) {
+ unsigned long a = 0;
+ lua_pushinteger(L, (L->top - L->stack));
+ lua_pushinteger(L, (L->stack_last - L->stack));
+ lua_pushinteger(L, (L->ci - L->base_ci));
+ lua_pushinteger(L, (L->end_ci - L->base_ci));
+ lua_pushinteger(L, (unsigned long)&a);
+ return 5;
+}
+
+
+static int table_query (lua_State *L) {
+ const Table *t;
+ int i = luaL_optint(L, 2, -1);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ t = hvalue(obj_at(L, 1));
+ if (i == -1) {
+ lua_pushinteger(L, t->sizearray);
+ lua_pushinteger(L, luaH_isdummy(t->node) ? 0 : sizenode(t));
+ lua_pushinteger(L, t->lastfree - t->node);
+ }
+ else if (i < t->sizearray) {
+ lua_pushinteger(L, i);
+ luaA_pushobject(L, &t->array[i]);
+ lua_pushnil(L);
+ }
+ else if ((i -= t->sizearray) < sizenode(t)) {
+ if (!ttisnil(gval(gnode(t, i))) ||
+ ttisnil(gkey(gnode(t, i))) ||
+ ttisnumber(gkey(gnode(t, i)))) {
+ luaA_pushobject(L, key2tval(gnode(t, i)));
+ }
+ else
+ lua_pushliteral(L, "<undef>");
+ luaA_pushobject(L, gval(gnode(t, i)));
+ if (gnext(&t->node[i]))
+ lua_pushinteger(L, gnext(&t->node[i]) - t->node);
+ else
+ lua_pushnil(L);
+ }
+ return 3;
+}
+
+
+static int string_query (lua_State *L) {
+ stringtable *tb = &G(L)->strt;
+ int s = luaL_optint(L, 2, 0) - 1;
+ if (s==-1) {
+ lua_pushinteger(L ,tb->nuse);
+ lua_pushinteger(L ,tb->size);
+ return 2;
+ }
+ else if (s < tb->size) {
+ GCObject *ts;
+ int n = 0;
+ for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
+ setsvalue2s(L, L->top, gco2ts(ts));
+ incr_top(L);
+ n++;
+ }
+ return n;
+ }
+ return 0;
+}
+
+
+static int tref (lua_State *L) {
+ int level = lua_gettop(L);
+ int lock = luaL_optint(L, 2, 1);
+ luaL_checkany(L, 1);
+ lua_pushvalue(L, 1);
+ lua_pushinteger(L, lua_ref(L, lock));
+ lua_assert(lua_gettop(L) == level+1); /* +1 for result */
+ return 1;
+}
+
+static int getref (lua_State *L) {
+ int level = lua_gettop(L);
+ lua_getref(L, luaL_checkint(L, 1));
+ lua_assert(lua_gettop(L) == level+1);
+ return 1;
+}
+
+static int unref (lua_State *L) {
+ int level = lua_gettop(L);
+ lua_unref(L, luaL_checkint(L, 1));
+ lua_assert(lua_gettop(L) == level);
+ return 0;
+}
+
+
+static int upvalue (lua_State *L) {
+ int n = luaL_checkint(L, 2);
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ if (lua_isnone(L, 3)) {
+ const char *name = lua_getupvalue(L, 1, n);
+ if (name == NULL) return 0;
+ lua_pushstring(L, name);
+ return 2;
+ }
+ else {
+ const char *name = lua_setupvalue(L, 1, n);
+ lua_pushstring(L, name);
+ return 1;
+ }
+}
+
+
+static int newuserdata (lua_State *L) {
+ size_t size = luaL_checkint(L, 1);
+ char *p = cast(char *, lua_newuserdata(L, size));
+ while (size--) *p++ = '\0';
+ return 1;
+}
+
+
+static int pushuserdata (lua_State *L) {
+ lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+static int udataval (lua_State *L) {
+ lua_pushinteger(L, cast(long, lua_touserdata(L, 1)));
+ return 1;
+}
+
+
+static int doonnewstack (lua_State *L) {
+ lua_State *L1 = lua_newthread(L);
+ size_t l;
+ const char *s = luaL_checklstring(L, 1, &l);
+ int status = luaL_loadbuffer(L1, s, l, s);
+ if (status == 0)
+ status = lua_pcall(L1, 0, 0, 0);
+ lua_pushinteger(L, status);
+ return 1;
+}
+
+
+static int s2d (lua_State *L) {
+ lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
+ return 1;
+}
+
+
+static int d2s (lua_State *L) {
+ double d = luaL_checknumber(L, 1);
+ lua_pushlstring(L, cast(char *, &d), sizeof(d));
+ return 1;
+}
+
+
+static int num2int (lua_State *L) {
+ lua_pushinteger(L, lua_tointeger(L, 1));
+ return 1;
+}
+
+
+static int newstate (lua_State *L) {
+ void *ud;
+ lua_Alloc f = lua_getallocf(L, &ud);
+ lua_State *L1 = lua_newstate(f, ud);
+ if (L1)
+ lua_pushinteger(L, (unsigned long)L1);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+
+static int loadlib (lua_State *L) {
+ static const luaL_Reg libs[] = {
+ {"baselibopen", luaopen_base},
+ {"dblibopen", luaopen_debug},
+ {"iolibopen", luaopen_io},
+ {"mathlibopen", luaopen_math},
+ {"strlibopen", luaopen_string},
+ {"tablibopen", luaopen_table},
+ {"packageopen", luaopen_package},
+ {NULL, NULL}
+ };
+ lua_State *L1 = cast(lua_State *,
+ cast(unsigned long, luaL_checknumber(L, 1)));
+ lua_pushvalue(L1, LUA_GLOBALSINDEX);
+ luaL_register(L1, NULL, libs);
+ return 0;
+}
+
+static int closestate (lua_State *L) {
+ lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
+ lua_close(L1);
+ return 0;
+}
+
+static int doremote (lua_State *L) {
+ lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
+ size_t lcode;
+ const char *code = luaL_checklstring(L, 2, &lcode);
+ int status;
+ lua_settop(L1, 0);
+ status = luaL_loadbuffer(L1, code, lcode, code);
+ if (status == 0)
+ status = lua_pcall(L1, 0, LUA_MULTRET, 0);
+ if (status != 0) {
+ lua_pushnil(L);
+ lua_pushinteger(L, status);
+ lua_pushstring(L, lua_tostring(L1, -1));
+ return 3;
+ }
+ else {
+ int i = 0;
+ while (!lua_isnone(L1, ++i))
+ lua_pushstring(L, lua_tostring(L1, i));
+ lua_pop(L1, i-1);
+ return i-1;
+ }
+}
+
+
+static int log2_aux (lua_State *L) {
+ lua_pushinteger(L, luaO_log2(luaL_checkint(L, 1)));
+ return 1;
+}
+
+static int int2fb_aux (lua_State *L) {
+ int b = luaO_int2fb(luaL_checkint(L, 1));
+ lua_pushinteger(L, b);
+ lua_pushinteger(L, luaO_fb2int(b));
+ return 2;
+}
+
+
+
+/*
+** {======================================================
+** function to test the API with C. It interprets a kind of assembler
+** language with calls to the API, so the test can be driven by Lua code
+** =======================================================
+*/
+
+static const char *const delimits = " \t\n,;";
+
+static void skip (const char **pc) {
+ while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
+}
+
+static int getnum_aux (lua_State *L, const char **pc) {
+ int res = 0;
+ int sig = 1;
+ skip(pc);
+ if (**pc == '.') {
+ res = cast_int(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ (*pc)++;
+ return res;
+ }
+ else if (**pc == '-') {
+ sig = -1;
+ (*pc)++;
+ }
+ while (isdigit(cast_int(**pc))) res = res*10 + (*(*pc)++) - '0';
+ return sig*res;
+}
+
+static const char *getname_aux (char *buff, const char **pc) {
+ int i = 0;
+ skip(pc);
+ while (**pc != '\0' && !strchr(delimits, **pc))
+ buff[i++] = *(*pc)++;
+ buff[i] = '\0';
+ return buff;
+}
+
+
+static int getindex_aux (lua_State *L, const char **pc) {
+ skip(pc);
+ switch (*(*pc)++) {
+ case 'R': return LUA_REGISTRYINDEX;
+ case 'G': return LUA_GLOBALSINDEX;
+ case 'E': return LUA_ENVIRONINDEX;
+ case 'U': return lua_upvalueindex(getnum_aux(L, pc));
+ default: (*pc)--; return getnum_aux(L, pc);
+ }
+}
+
+#define EQ(s1) (strcmp(s1, inst) == 0)
+
+#define getnum (getnum_aux(L, &pc))
+#define getname (getname_aux(buff, &pc))
+#define getindex (getindex_aux(L, &pc))
+
+
+static int testC (lua_State *L) {
+ char buff[30];
+ lua_State *L1;
+ const char *pc;
+ if (lua_isnumber(L, 1)) {
+ L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
+ pc = luaL_checkstring(L, 2);
+ }
+ else {
+ L1 = L;
+ pc = luaL_checkstring(L, 1);
+ }
+ for (;;) {
+ const char *inst = getname;
+ if EQ("") return 0;
+ else if EQ("isnumber") {
+ lua_pushinteger(L1, lua_isnumber(L1, getindex));
+ }
+ else if EQ("isstring") {
+ lua_pushinteger(L1, lua_isstring(L1, getindex));
+ }
+ else if EQ("istable") {
+ lua_pushinteger(L1, lua_istable(L1, getindex));
+ }
+ else if EQ("iscfunction") {
+ lua_pushinteger(L1, lua_iscfunction(L1, getindex));
+ }
+ else if EQ("isfunction") {
+ lua_pushinteger(L1, lua_isfunction(L1, getindex));
+ }
+ else if EQ("isuserdata") {
+ lua_pushinteger(L1, lua_isuserdata(L1, getindex));
+ }
+ else if EQ("isudataval") {
+ lua_pushinteger(L1, lua_islightuserdata(L1, getindex));
+ }
+ else if EQ("isnil") {
+ lua_pushinteger(L1, lua_isnil(L1, getindex));
+ }
+ else if EQ("isnull") {
+ lua_pushinteger(L1, lua_isnone(L1, getindex));
+ }
+ else if EQ("tonumber") {
+ lua_pushnumber(L1, lua_tonumber(L1, getindex));
+ }
+ else if EQ("tostring") {
+ const char *s = lua_tostring(L1, getindex);
+ lua_pushstring(L1, s);
+ }
+ else if EQ("objsize") {
+ lua_pushinteger(L1, lua_objlen(L1, getindex));
+ }
+ else if EQ("tocfunction") {
+ lua_pushcfunction(L1, lua_tocfunction(L1, getindex));
+ }
+ else if EQ("return") {
+ return getnum;
+ }
+ else if EQ("gettop") {
+ lua_pushinteger(L1, lua_gettop(L1));
+ }
+ else if EQ("settop") {
+ lua_settop(L1, getnum);
+ }
+ else if EQ("pop") {
+ lua_pop(L1, getnum);
+ }
+ else if EQ("pushnum") {
+ lua_pushinteger(L1, getnum);
+ }
+ else if EQ("pushstring") {
+ lua_pushstring(L1, getname);
+ }
+ else if EQ("pushnil") {
+ lua_pushnil(L1);
+ }
+ else if EQ("pushbool") {
+ lua_pushboolean(L1, getnum);
+ }
+ else if EQ("newuserdata") {
+ lua_newuserdata(L1, getnum);
+ }
+ else if EQ("tobool") {
+ lua_pushinteger(L1, lua_toboolean(L1, getindex));
+ }
+ else if EQ("pushvalue") {
+ lua_pushvalue(L1, getindex);
+ }
+ else if EQ("pushcclosure") {
+ lua_pushcclosure(L1, testC, getnum);
+ }
+ else if EQ("remove") {
+ lua_remove(L1, getnum);
+ }
+ else if EQ("insert") {
+ lua_insert(L1, getnum);
+ }
+ else if EQ("replace") {
+ lua_replace(L1, getindex);
+ }
+ else if EQ("gettable") {
+ lua_gettable(L1, getindex);
+ }
+ else if EQ("settable") {
+ lua_settable(L1, getindex);
+ }
+ else if EQ("next") {
+ lua_next(L1, -2);
+ }
+ else if EQ("concat") {
+ lua_concat(L1, getnum);
+ }
+ else if EQ("lessthan") {
+ int a = getindex;
+ lua_pushboolean(L1, lua_lessthan(L1, a, getindex));
+ }
+ else if EQ("equal") {
+ int a = getindex;
+ lua_pushboolean(L1, lua_equal(L1, a, getindex));
+ }
+ else if EQ("rawcall") {
+ int narg = getnum;
+ int nres = getnum;
+ lua_call(L1, narg, nres);
+ }
+ else if EQ("call") {
+ int narg = getnum;
+ int nres = getnum;
+ lua_pcall(L1, narg, nres, 0);
+ }
+ else if EQ("loadstring") {
+ size_t sl;
+ const char *s = luaL_checklstring(L1, getnum, &sl);
+ luaL_loadbuffer(L1, s, sl, s);
+ }
+ else if EQ("loadfile") {
+ luaL_loadfile(L1, luaL_checkstring(L1, getnum));
+ }
+ else if EQ("setmetatable") {
+ lua_setmetatable(L1, getindex);
+ }
+ else if EQ("getmetatable") {
+ if (lua_getmetatable(L1, getindex) == 0)
+ lua_pushnil(L1);
+ }
+ else if EQ("type") {
+ lua_pushstring(L1, luaL_typename(L1, getnum));
+ }
+ else if EQ("getn") {
+ int i = getindex;
+ lua_pushinteger(L1, luaL_getn(L1, i));
+ }
+#ifndef luaL_setn
+ else if EQ("setn") {
+ int i = getindex;
+ int n = cast_int(lua_tonumber(L1, -1));
+ luaL_setn(L1, i, n);
+ lua_pop(L1, 1);
+ }
+#endif
+ else if EQ("throw") {
+#if defined(__cplusplus)
+static struct X { int x; } x;
+ throw x;
+#else
+ luaL_error(L1, "C++");
+#endif
+ break;
+ }
+ else luaL_error(L, "unknown instruction %s", buff);
+ }
+ return 0;
+}
+
+/* }====================================================== */
+
+
+/*
+** {======================================================
+** tests for yield inside hooks
+** =======================================================
+*/
+
+static void yieldf (lua_State *L, lua_Debug *ar) {
+ lua_yield(L, 0);
+}
+
+static int setyhook (lua_State *L) {
+ if (lua_isnoneornil(L, 1))
+ lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+ else {
+ const char *smask = luaL_checkstring(L, 1);
+ int count = luaL_optint(L, 2, 0);
+ int mask = 0;
+ if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
+ if (count > 0) mask |= LUA_MASKCOUNT;
+ lua_sethook(L, yieldf, mask, count);
+ }
+ return 0;
+}
+
+
+static int coresume (lua_State *L) {
+ int status;
+ lua_State *co = lua_tothread(L, 1);
+ luaL_argcheck(L, co, 1, "coroutine expected");
+ status = lua_resume(co, 0);
+ if (status != 0) {
+ lua_pushboolean(L, 0);
+ lua_insert(L, -2);
+ return 2; /* return false + error message */
+ }
+ else {
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+}
+
+/* }====================================================== */
+
+
+
+/*
+** {======================================================
+** tests auxlib functions
+** =======================================================
+*/
+
+static int auxgsub (lua_State *L) {
+ const char *s1 = luaL_checkstring(L, 1);
+ const char *s2 = luaL_checkstring(L, 2);
+ const char *s3 = luaL_checkstring(L, 3);
+ lua_settop(L, 3);
+ luaL_gsub(L, s1, s2, s3);
+ lua_assert(lua_gettop(L) == 4);
+ return 1;
+}
+
+
+/* }====================================================== */
+
+
+
+static const struct luaL_Reg tests_funcs[] = {
+ {"checkmemory", lua_checkmemory},
+ {"closestate", closestate},
+ {"d2s", d2s},
+ {"doonnewstack", doonnewstack},
+ {"doremote", doremote},
+ {"gccolor", get_gccolor},
+ {"gcstate", gcstate},
+ {"getref", getref},
+ {"gsub", auxgsub},
+ {"hash", hash_query},
+ {"int2fb", int2fb_aux},
+ {"limits", get_limits},
+ {"listcode", listcode},
+ {"listk", listk},
+ {"listlocals", listlocals},
+ {"loadlib", loadlib},
+ {"log2", log2_aux},
+ {"newstate", newstate},
+ {"newuserdata", newuserdata},
+ {"num2int", num2int},
+ {"pushuserdata", pushuserdata},
+ {"querystr", string_query},
+ {"querytab", table_query},
+ {"ref", tref},
+ {"resume", coresume},
+ {"s2d", s2d},
+ {"setyhook", setyhook},
+ {"stacklevel", stacklevel},
+ {"testC", testC},
+ {"totalmem", mem_query},
+ {"trick", settrick},
+ {"udataval", udataval},
+ {"unref", unref},
+ {"upvalue", upvalue},
+ {NULL, NULL}
+};
+
+
+int luaB_opentests (lua_State *L) {
+ void *ud;
+ lua_assert(lua_getallocf(L, &ud) == debug_realloc);
+ lua_assert(ud == cast(void *, &memcontrol));
+ lua_setallocf(L, lua_getallocf(L, NULL), ud);
+ lua_state = L; /* keep first state to be opened */
+ luaL_register(L, "T", tests_funcs);
+ return 0;
+}
+
+
+#undef main
+int main (int argc, char *argv[]) {
+ int ret;
+ char *limit = getenv("MEMLIMIT");
+ if (limit)
+ memcontrol.memlimit = strtoul(limit, NULL, 10);
+ ret = l_main(argc, argv);
+ lua_assert(memcontrol.numblocks == 0);
+ lua_assert(memcontrol.total == 0);
+ return ret;
+}
+
+#endif
diff --git a/test/PUC-Lua-5.1-tests/etc/ltests.h b/test/PUC-Lua-5.1-tests/etc/ltests.h
new file mode 100644
index 0000000..e570212
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/etc/ltests.h
@@ -0,0 +1,92 @@
+/*
+** $Id: ltests.h,v 2.17 2005/12/27 17:12:00 roberto Exp $
+** Internal Header for Debugging of the Lua Implementation
+** See Copyright Notice in lua.h
+*/
+
+#ifndef ltests_h
+#define ltests_h
+
+
+#include <stdlib.h>
+
+
+#define LUA_DEBUG
+
+#undef NDEBUG
+#include <assert.h>
+#define lua_assert(c) assert(c)
+
+
+/* to avoid warnings, and to make sure value is really unused */
+#define UNUSED(x) (x=0, (void)(x))
+
+
+/* memory allocator control variables */
+typedef struct Memcontrol {
+ unsigned long numblocks;
+ unsigned long total;
+ unsigned long maxmem;
+ unsigned long memlimit;
+} Memcontrol;
+
+LUAI_DATA Memcontrol memcontrol;
+
+
+/*
+** generic variable for debug tricks
+*/
+LUAI_DATA int Trick;
+
+
+void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
+
+#ifdef lua_c
+#define luaL_newstate() lua_newstate(debug_realloc, &memcontrol)
+#endif
+
+
+typedef struct CallInfo *pCallInfo;
+
+int lua_checkmemory (lua_State *L);
+int lua_checkpc (lua_State *L, pCallInfo ci);
+
+
+/* test for lock/unlock */
+#undef luai_userstateopen
+#undef luai_userstatethread
+#undef lua_lock
+#undef lua_unlock
+#undef LUAI_EXTRASPACE
+
+struct L_EXTRA { int lock; int *plock; };
+#define LUAI_EXTRASPACE sizeof(struct L_EXTRA)
+#define getlock(l) (cast(struct L_EXTRA *, l) - 1)
+#define luai_userstateopen(l) \
+ (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock))
+#define luai_userstatethread(l,l1) (getlock(l1)->plock = getlock(l)->plock)
+#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0)
+#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0)
+
+
+int luaB_opentests (lua_State *L);
+
+#ifdef lua_c
+#define luaL_openlibs(L) { (luaL_openlibs)(L); luaB_opentests(L); }
+#endif
+
+
+
+/* real main will be defined at `ltests.c' */
+int l_main (int argc, char *argv[]);
+#define main l_main
+
+
+
+/* change some sizes to give some bugs a chance */
+
+#undef LUAL_BUFFERSIZE
+#define LUAL_BUFFERSIZE 27
+#define MINSTRTABSIZE 2
+
+#endif
diff --git a/test/PUC-Lua-5.1-tests/events.lua b/test/PUC-Lua-5.1-tests/events.lua
new file mode 100644
index 0000000..5234b00
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/events.lua
@@ -0,0 +1,360 @@
+print('testing metatables')
+
+X = 20; B = 30
+
+setfenv(1, setmetatable({}, {__index=_G}))
+
+collectgarbage()
+
+X = X+10
+assert(X == 30 and _G.X == 20)
+B = false
+assert(B == false)
+B = nil
+assert(B == 30)
+
+assert(getmetatable{} == nil)
+assert(getmetatable(4) == nil)
+assert(getmetatable(nil) == nil)
+a={}; setmetatable(a, {__metatable = "xuxu",
+ __tostring=function(x) return x.name end})
+assert(getmetatable(a) == "xuxu")
+assert(tostring(a) == nil)
+-- cannot change a protected metatable
+assert(pcall(setmetatable, a, {}) == false)
+a.name = "gororoba"
+assert(tostring(a) == "gororoba")
+
+local a, t = {10,20,30; x="10", y="20"}, {}
+assert(setmetatable(a,t) == a)
+assert(getmetatable(a) == t)
+assert(setmetatable(a,nil) == a)
+assert(getmetatable(a) == nil)
+assert(setmetatable(a,t) == a)
+
+
+function f (t, i, e)
+ assert(not e)
+ local p = rawget(t, "parent")
+ return (p and p[i]+3), "dummy return"
+end
+
+t.__index = f
+
+a.parent = {z=25, x=12, [4] = 24}
+assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
+
+collectgarbage()
+
+a = setmetatable({}, t)
+function f(t, i, v) rawset(t, i, v-3) end
+t.__newindex = f
+a[1] = 30; a.x = "101"; a[5] = 200
+assert(a[1] == 27 and a.x == 98 and a[5] == 197)
+
+
+local c = {}
+a = setmetatable({}, t)
+t.__newindex = c
+a[1] = 10; a[2] = 20; a[3] = 90
+assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
+
+
+do
+ local a;
+ a = setmetatable({}, {__index = setmetatable({},
+ {__index = setmetatable({},
+ {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
+ a[0] = 20
+ for i=0,10 do
+ assert(a[i*3] == 20 + i*4)
+ end
+end
+
+
+do -- newindex
+ local foi
+ local a = {}
+ for i=1,10 do a[i] = 0; a['a'..i] = 0; end
+ setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
+ foi = false; a[1]=0; assert(not foi)
+ foi = false; a['a1']=0; assert(not foi)
+ foi = false; a['a11']=0; assert(foi)
+ foi = false; a[11]=0; assert(foi)
+ foi = false; a[1]=nil; assert(not foi)
+ foi = false; a[1]=nil; assert(foi)
+end
+
+
+function f (t, ...) return t, {...} end
+t.__call = f
+
+do
+ local x,y = a(unpack{'a', 1})
+ assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
+ x,y = a()
+ assert(x==a and y[1]==nil)
+end
+
+
+local b = setmetatable({}, t)
+setmetatable(b,t)
+
+function f(op)
+ return function (...) cap = {[0] = op, ...} ; return (...) end
+end
+t.__add = f("add")
+t.__sub = f("sub")
+t.__mul = f("mul")
+t.__div = f("div")
+t.__mod = f("mod")
+t.__unm = f("unm")
+t.__pow = f("pow")
+
+assert(b+5 == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
+assert(b+'5' == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
+assert(5+b == 5)
+assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
+assert('5'+b == '5')
+assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
+b=b-3; assert(getmetatable(b) == t)
+assert(5-a == 5)
+assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
+assert('5'-a == '5')
+assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
+assert(a*a == a)
+assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
+assert(a/0 == a)
+assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
+assert(a%2 == a)
+assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
+assert(-a == a)
+assert(cap[0] == "unm" and cap[1] == a)
+assert(a^4 == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
+assert(a^'4' == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
+assert(4^a == 4)
+assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
+assert('4'^a == '4')
+assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
+
+
+t = {}
+t.__lt = function (a,b,c)
+ collectgarbage()
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<b, "dummy"
+end
+
+function Op(x) return setmetatable({x=x}, t) end
+
+local function test ()
+ assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
+ assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
+ assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
+ assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
+ assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
+ assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
+ assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
+ assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
+end
+
+test()
+
+t.__le = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<=b, "dummy"
+end
+
+test() -- retest comparisons, now using both `lt' and `le'
+
+
+-- test `partial order'
+
+local function Set(x)
+ local y = {}
+ for _,k in pairs(x) do y[k] = 1 end
+ return setmetatable(y, t)
+end
+
+t.__lt = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) ~= nil
+end
+
+t.__le = nil
+
+assert(Set{1,2,3} < Set{1,2,3,4})
+assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
+assert((Set{1,2,3,4} <= Set{1,2,3,4}))
+assert((Set{1,2,3,4} >= Set{1,2,3,4}))
+assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
+
+t.__le = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ end
+ return true
+end
+
+assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
+assert(not(Set{1,3} <= Set{3,5}))
+assert(not(Set{1,3} >= Set{3,5}))
+
+t.__eq = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) == nil
+end
+
+local s = Set{1,3,5}
+assert(s == Set{3,5,1})
+assert(not rawequal(s, Set{3,5,1}))
+assert(rawequal(s, s))
+assert(Set{1,3,5,1} == Set{3,5,1})
+assert(Set{1,3,5} ~= Set{3,5,1,6})
+t[Set{1,3,5}] = 1
+assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
+
+
+t.__concat = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.val end
+ if type(b) == 'table' then b = b.val end
+ if A then return a..b
+ else
+ return setmetatable({val=a..b}, t)
+ end
+end
+
+c = {val="c"}; setmetatable(c, t)
+d = {val="d"}; setmetatable(d, t)
+
+A = true
+assert(c..d == 'cd')
+assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
+
+A = false
+x = c..d
+assert(getmetatable(x) == t and x.val == 'cd')
+x = 0 .."a".."b"..c..d.."e".."f".."g"
+assert(x.val == "0abcdefg")
+
+
+-- test comparison compatibilities
+local t1, t2, c, d
+t1 = {}; c = {}; setmetatable(c, t1)
+d = {}
+t1.__eq = function () return true end
+t1.__lt = function () return true end
+assert(c ~= d and not pcall(function () return c < d end))
+setmetatable(d, t1)
+assert(c == d and c < d and not(d <= c))
+t2 = {}
+t2.__eq = t1.__eq
+t2.__lt = t1.__lt
+setmetatable(d, t2)
+assert(c == d and c < d and not(d <= c))
+
+
+
+-- test for several levels of calls
+local i
+local tt = {
+ __call = function (t, ...)
+ i = i+1
+ if t.f then return t.f(...)
+ else return {...}
+ end
+ end
+}
+
+local a = setmetatable({}, tt)
+local b = setmetatable({f=a}, tt)
+local c = setmetatable({f=b}, tt)
+
+i = 0
+x = c(3,4,5)
+assert(i == 3 and x[1] == 3 and x[3] == 5)
+
+
+assert(_G.X == 20)
+assert(_G == getfenv(0))
+
+print'+'
+
+local _g = _G
+setfenv(1, setmetatable({}, {__index=function (_,k) return _g[k] end}))
+
+-- testing proxies
+assert(getmetatable(newproxy()) == nil)
+assert(getmetatable(newproxy(false)) == nil)
+
+local u = newproxy(true)
+
+getmetatable(u).__newindex = function (u,k,v)
+ getmetatable(u)[k] = v
+end
+
+getmetatable(u).__index = function (u,k)
+ return getmetatable(u)[k]
+end
+
+for i=1,10 do u[i] = i end
+for i=1,10 do assert(u[i] == i) end
+
+local k = newproxy(u)
+assert(getmetatable(k) == getmetatable(u))
+
+
+a = {}
+rawset(a, "x", 1, 2, 3)
+assert(a.x == 1 and rawget(a, "x", 3) == 1)
+
+print '+'
+
+-- testing metatables for basic types
+mt = {}
+debug.setmetatable(10, mt)
+assert(getmetatable(-2) == mt)
+mt.__index = function (a,b) return a+b end
+assert((10)[3] == 13)
+assert((10)["3"] == 13)
+debug.setmetatable(23, nil)
+assert(getmetatable(-2) == nil)
+
+debug.setmetatable(true, mt)
+assert(getmetatable(false) == mt)
+mt.__index = function (a,b) return a or b end
+assert((true)[false] == true)
+assert((false)[false] == false)
+debug.setmetatable(false, nil)
+assert(getmetatable(true) == nil)
+
+debug.setmetatable(nil, mt)
+assert(getmetatable(nil) == mt)
+mt.__add = function (a,b) return (a or 0) + (b or 0) end
+assert(10 + nil == 10)
+assert(nil + 23 == 23)
+assert(nil + nil == 0)
+debug.setmetatable(nil, nil)
+assert(getmetatable(nil) == nil)
+
+debug.setmetatable(nil, {})
+
+
+print 'OK'
+
+return 12
diff --git a/test/PUC-Lua-5.1-tests/files.lua b/test/PUC-Lua-5.1-tests/files.lua
new file mode 100644
index 0000000..903488c
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/files.lua
@@ -0,0 +1,324 @@
+
+print('testing i/o')
+
+assert(io.input(io.stdin) == io.stdin)
+assert(io.output(io.stdout) == io.stdout)
+
+
+assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
+assert(io.type(8) == nil)
+local a = {}; setmetatable(a, {})
+assert(io.type(a) == nil)
+
+local a,b,c = io.open('xuxu_nao_existe')
+assert(not a and type(b) == "string" and type(c) == "number")
+
+a,b,c = io.open('/a/b/c/d', 'w')
+assert(not a and type(b) == "string" and type(c) == "number")
+
+local file = os.tmpname()
+local otherfile = os.tmpname()
+
+assert(os.setlocale('C', 'all'))
+
+io.input(io.stdin); io.output(io.stdout);
+
+os.remove(file)
+assert(loadfile(file) == nil)
+assert(io.open(file) == nil)
+io.output(file)
+assert(io.output() ~= io.stdout)
+
+assert(io.output():seek() == 0)
+assert(io.write("alo alo"))
+assert(io.output():seek() == string.len("alo alo"))
+assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
+assert(io.write("joao"))
+assert(io.output():seek("end") == string.len("alo joao"))
+
+assert(io.output():seek("set") == 0)
+
+assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
+assert(io.write('çfourth_line'))
+io.output(io.stdout)
+collectgarbage() -- file should be closed by GC
+assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
+print('+')
+
+-- test GC for files
+collectgarbage()
+for i=1,120 do
+ for i=1,5 do
+ io.input(file)
+ assert(io.open(file, 'r'))
+ io.lines(file)
+ end
+ collectgarbage()
+end
+
+assert(os.rename(file, otherfile))
+assert(os.rename(file, otherfile) == nil)
+
+io.output(io.open(otherfile, "a"))
+assert(io.write("\n\n\t\t 3450\n"));
+io.close()
+
+-- test line generators
+assert(os.rename(otherfile, file))
+io.output(otherfile)
+local f = io.lines(file)
+while f() do end;
+assert(not pcall(f)) -- read lines after EOF
+assert(not pcall(f)) -- read lines after EOF
+-- copy from file to otherfile
+for l in io.lines(file) do io.write(l, "\n") end
+io.close()
+-- copy from otherfile back to file
+local f = assert(io.open(otherfile))
+assert(io.type(f) == "file")
+io.output(file)
+assert(io.output():read() == nil)
+for l in f:lines() do io.write(l, "\n") end
+assert(f:close()); io.close()
+assert(not pcall(io.close, f)) -- error trying to close again
+assert(tostring(f) == "file (closed)")
+assert(io.type(f) == "closed file")
+io.input(file)
+f = io.open(otherfile):lines()
+for l in io.lines() do assert(l == f()) end
+assert(os.remove(otherfile))
+
+io.input(file)
+do -- test error returns
+ local a,b,c = io.input():write("xuxu")
+ assert(not a and type(b) == "string" and type(c) == "number")
+end
+assert(io.read(0) == "") -- not eof
+assert(io.read(5, '*l') == '"álo"')
+assert(io.read(0) == "")
+assert(io.read() == "second line")
+local x = io.input():seek()
+assert(io.read() == "third line ")
+assert(io.input():seek("set", x))
+assert(io.read('*l') == "third line ")
+assert(io.read(1) == "ç")
+assert(io.read(string.len"fourth_line") == "fourth_line")
+assert(io.input():seek("cur", -string.len"fourth_line"))
+assert(io.read() == "fourth_line")
+assert(io.read() == "") -- empty line
+assert(io.read('*n') == 3450)
+assert(io.read(1) == '\n')
+assert(io.read(0) == nil) -- end of file
+assert(io.read(1) == nil) -- end of file
+assert(({io.read(1)})[2] == nil)
+assert(io.read() == nil) -- end of file
+assert(({io.read()})[2] == nil)
+assert(io.read('*n') == nil) -- end of file
+assert(({io.read('*n')})[2] == nil)
+assert(io.read('*a') == '') -- end of file (OK for `*a')
+assert(io.read('*a') == '') -- end of file (OK for `*a')
+collectgarbage()
+print('+')
+io.close(io.input())
+assert(not pcall(io.read))
+
+assert(os.remove(file))
+
+local t = '0123456789'
+for i=1,12 do t = t..t; end
+assert(string.len(t) == 10*2^12)
+
+io.output(file)
+io.write("alo\n")
+io.close()
+assert(not pcall(io.write))
+local f = io.open(file, "a")
+io.output(f)
+collectgarbage()
+
+assert(io.write(' ' .. t .. ' '))
+assert(io.write(';', 'end of file\n'))
+f:flush(); io.flush()
+f:close()
+print('+')
+
+io.input(file)
+assert(io.read() == "alo")
+assert(io.read(1) == ' ')
+assert(io.read(string.len(t)) == t)
+assert(io.read(1) == ' ')
+assert(io.read(0))
+assert(io.read('*a') == ';end of file\n')
+assert(io.read(0) == nil)
+assert(io.close(io.input()))
+
+assert(os.remove(file))
+print('+')
+
+local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
+io.output(file)
+assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
+io.close()
+assert(loadfile(file))()
+assert(x1 == x2)
+print('+')
+assert(os.remove(file))
+assert(os.remove(file) == nil)
+assert(os.remove(otherfile) == nil)
+
+io.output(file)
+assert(io.write("qualquer coisa\n"))
+assert(io.write("mais qualquer coisa"))
+io.close()
+io.output(assert(io.open(otherfile, 'wb')))
+assert(io.write("outra coisa\0\1\3\0\0\0\0\255\0"))
+io.close()
+
+local filehandle = assert(io.open(file, 'r'))
+local otherfilehandle = assert(io.open(otherfile, 'rb'))
+assert(filehandle ~= otherfilehandle)
+assert(type(filehandle) == "userdata")
+assert(filehandle:read('*l') == "qualquer coisa")
+io.input(otherfilehandle)
+assert(io.read(string.len"outra coisa") == "outra coisa")
+assert(filehandle:read('*l') == "mais qualquer coisa")
+filehandle:close();
+assert(type(filehandle) == "userdata")
+io.input(otherfilehandle)
+assert(io.read(4) == "\0\1\3\0")
+assert(io.read(3) == "\0\0\0")
+assert(io.read(0) == "") -- 255 is not eof
+assert(io.read(1) == "\255")
+assert(io.read('*a') == "\0")
+assert(not io.read(0))
+assert(otherfilehandle == io.input())
+otherfilehandle:close()
+assert(os.remove(file))
+assert(os.remove(otherfile))
+collectgarbage()
+
+io.output(file)
+io.write[[
+ 123.4 -56e-2 not a number
+second line
+third line
+
+and the rest of the file
+]]
+io.close()
+io.input(file)
+local _,a,b,c,d,e,h,__ = io.read(1, '*n', '*n', '*l', '*l', '*l', '*a', 10)
+assert(io.close(io.input()))
+assert(_ == ' ' and __ == nil)
+assert(type(a) == 'number' and a==123.4 and b==-56e-2)
+assert(d=='second line' and e=='third line')
+assert(h==[[
+
+and the rest of the file
+]])
+assert(os.remove(file))
+collectgarbage()
+
+-- testing buffers
+do
+ local f = assert(io.open(file, "w"))
+ local fr = assert(io.open(file, "r"))
+ assert(f:setvbuf("full", 2000))
+ f:write("x")
+ assert(fr:read("*all") == "") -- full buffer; output not written yet
+ f:close()
+ fr:seek("set")
+ assert(fr:read("*all") == "x") -- `close' flushes it
+ f = assert(io.open(file), "w")
+ assert(f:setvbuf("no"))
+ f:write("x")
+ fr:seek("set")
+ assert(fr:read("*all") == "x") -- no buffer; output is ready
+ f:close()
+ f = assert(io.open(file, "a"))
+ assert(f:setvbuf("line"))
+ f:write("x")
+ fr:seek("set", 1)
+ assert(fr:read("*all") == "") -- line buffer; no output without `\n'
+ f:write("a\n")
+ fr:seek("set", 1)
+ assert(fr:read("*all") == "xa\n") -- now we have a whole line
+ f:close(); fr:close()
+end
+
+
+-- testing large files (> BUFSIZ)
+io.output(file)
+for i=1,5001 do io.write('0123456789123') end
+io.write('\n12346')
+io.close()
+io.input(file)
+local x = io.read('*a')
+io.input():seek('set', 0)
+local y = io.read(30001)..io.read(1005)..io.read(0)..io.read(1)..io.read(100003)
+assert(x == y and string.len(x) == 5001*13 + 6)
+io.input():seek('set', 0)
+y = io.read() -- huge line
+assert(x == y..'\n'..io.read())
+assert(io.read() == nil)
+io.close(io.input())
+assert(os.remove(file))
+x = nil; y = nil
+
+x, y = pcall(io.popen, "ls")
+if x then
+ assert(y:read("*a"))
+ assert(y:close())
+else
+ (Message or print)('\a\n >>> popen not available<<<\n\a')
+end
+
+print'+'
+
+local t = os.time()
+T = os.date("*t", t)
+loadstring(os.date([[assert(T.year==%Y and T.month==%m and T.day==%d and
+ T.hour==%H and T.min==%M and T.sec==%S and
+ T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))()
+
+assert(os.time(T) == t)
+
+T = os.date("!*t", t)
+loadstring(os.date([[!assert(T.year==%Y and T.month==%m and T.day==%d and
+ T.hour==%H and T.min==%M and T.sec==%S and
+ T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))()
+
+do
+ local T = os.date("*t")
+ local t = os.time(T)
+ assert(type(T.isdst) == 'boolean')
+ T.isdst = nil
+ local t1 = os.time(T)
+ assert(t == t1) -- if isdst is absent uses correct default
+end
+
+t = os.time(T)
+T.year = T.year-1;
+local t1 = os.time(T)
+-- allow for leap years
+assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
+
+t = os.time()
+t1 = os.time(os.date("*t"))
+assert(os.difftime(t1,t) <= 2)
+
+local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12, sec=17}
+local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
+assert(os.difftime(t1,t2) == 60*2-2)
+
+io.output(io.stdout)
+local d = os.date('%d')
+local m = os.date('%m')
+local a = os.date('%Y')
+local ds = os.date('%w') + 1
+local h = os.date('%H')
+local min = os.date('%M')
+local s = os.date('%S')
+io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
+io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
+io.write(string.format('%s\n', _VERSION))
diff --git a/test/PUC-Lua-5.1-tests/gc.lua b/test/PUC-Lua-5.1-tests/gc.lua
new file mode 100644
index 0000000..86a9f75
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/gc.lua
@@ -0,0 +1,312 @@
+print('testing garbage collection')
+
+collectgarbage()
+
+_G["while"] = 234
+
+limit = 5000
+
+
+
+contCreate = 0
+
+print('tables')
+while contCreate <= limit do
+ local a = {}; a = nil
+ contCreate = contCreate+1
+end
+
+a = "a"
+
+contCreate = 0
+print('strings')
+while contCreate <= limit do
+ a = contCreate .. "b";
+ a = string.gsub(a, '(%d%d*)', string.upper)
+ a = "a"
+ contCreate = contCreate+1
+end
+
+
+contCreate = 0
+
+a = {}
+
+print('functions')
+function a:test ()
+ while contCreate <= limit do
+ loadstring(string.format("function temp(a) return 'a%d' end", contCreate))()
+ assert(temp() == string.format('a%d', contCreate))
+ contCreate = contCreate+1
+ end
+end
+
+a:test()
+
+-- collection of functions without locals, globals, etc.
+do local f = function () end end
+
+
+print("functions with errors")
+prog = [[
+do
+ a = 10;
+ function foo(x,y)
+ a = sin(a+0.456-0.23e-12);
+ return function (z) return sin(%x+z) end
+ end
+ local x = function (w) a=a+w; end
+end
+]]
+do
+ local step = 1
+ if rawget(_G, "_soft") then step = 13 end
+ for i=1, string.len(prog), step do
+ for j=i, string.len(prog), step do
+ pcall(loadstring(string.sub(prog, i, j)))
+ end
+ end
+end
+
+print('long strings')
+x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
+assert(string.len(x)==80)
+s = ''
+n = 0
+k = 300
+while n < k do s = s..x; n=n+1; j=tostring(n) end
+assert(string.len(s) == k*80)
+s = string.sub(s, 1, 20000)
+s, i = string.gsub(s, '(%d%d%d%d)', math.sin)
+assert(i==20000/4)
+s = nil
+x = nil
+
+assert(_G["while"] == 234)
+
+
+local bytes = gcinfo()
+while 1 do
+ local nbytes = gcinfo()
+ if nbytes < bytes then break end -- run until gc
+ bytes = nbytes
+ a = {}
+end
+
+
+local function dosteps (siz)
+ collectgarbage()
+ collectgarbage"stop"
+ local a = {}
+ for i=1,100 do a[i] = {{}}; local b = {} end
+ local x = gcinfo()
+ local i = 0
+ repeat
+ i = i+1
+ until collectgarbage("step", siz)
+ assert(gcinfo() < x)
+ return i
+end
+
+assert(dosteps(0) > 10)
+assert(dosteps(6) < dosteps(2))
+assert(dosteps(10000) == 1)
+assert(collectgarbage("step", 1000000) == true)
+assert(collectgarbage("step", 1000000))
+
+
+do
+ local x = gcinfo()
+ collectgarbage()
+ collectgarbage"stop"
+ repeat
+ local a = {}
+ until gcinfo() > 1000
+ collectgarbage"restart"
+ repeat
+ local a = {}
+ until gcinfo() < 1000
+end
+
+lim = 15
+a = {}
+-- fill a with `collectable' indices
+for i=1,lim do a[{}] = i end
+b = {}
+for k,v in pairs(a) do b[k]=v end
+-- remove all indices and collect them
+for n in pairs(b) do
+ a[n] = nil
+ assert(type(n) == 'table' and next(n) == nil)
+ collectgarbage()
+end
+b = nil
+collectgarbage()
+for n in pairs(a) do error'cannot be here' end
+for i=1,lim do a[i] = i end
+for i=1,lim do assert(a[i] == i) end
+
+
+print('weak tables')
+a = {}; setmetatable(a, {__mode = 'k'});
+-- fill a with some `collectable' indices
+for i=1,lim do a[{}] = i end
+-- and some non-collectable ones
+for i=1,lim do local t={}; a[t]=t end
+for i=1,lim do a[i] = i end
+for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end
+collectgarbage()
+local i = 0
+for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end
+assert(i == 3*lim)
+
+a = {}; setmetatable(a, {__mode = 'v'});
+a[1] = string.rep('b', 21)
+collectgarbage()
+assert(a[1]) -- strings are *values*
+a[1] = nil
+-- fill a with some `collectable' values (in both parts of the table)
+for i=1,lim do a[i] = {} end
+for i=1,lim do a[i..'x'] = {} end
+-- and some non-collectable ones
+for i=1,lim do local t={}; a[t]=t end
+for i=1,lim do a[i+lim]=i..'x' end
+collectgarbage()
+local i = 0
+for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end
+assert(i == 2*lim)
+
+a = {}; setmetatable(a, {__mode = 'vk'});
+local x, y, z = {}, {}, {}
+-- keep only some items
+a[1], a[2], a[3] = x, y, z
+a[string.rep('$', 11)] = string.rep('$', 11)
+-- fill a with some `collectable' values
+for i=4,lim do a[i] = {} end
+for i=1,lim do a[{}] = i end
+for i=1,lim do local t={}; a[t]=t end
+collectgarbage()
+assert(next(a) ~= nil)
+local i = 0
+for k,v in pairs(a) do
+ assert((k == 1 and v == x) or
+ (k == 2 and v == y) or
+ (k == 3 and v == z) or k==v);
+ i = i+1
+end
+assert(i == 4)
+x,y,z=nil
+collectgarbage()
+assert(next(a) == string.rep('$', 11))
+
+
+-- testing userdata
+collectgarbage("stop") -- stop collection
+local u = newproxy(true)
+local s = 0
+local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'})
+for i=1,10 do a[newproxy(u)] = i end
+for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end
+local a1 = {}; for k,v in pairs(a) do a1[k] = v end
+for k,v in pairs(a1) do a[v] = k end
+for i =1,10 do assert(a[i]) end
+getmetatable(u).a = a1
+getmetatable(u).u = u
+do
+ local u = u
+ getmetatable(u).__gc = function (o)
+ assert(a[o] == 10-s)
+ assert(a[10-s] == nil) -- udata already removed from weak table
+ assert(getmetatable(o) == getmetatable(u))
+ assert(getmetatable(o).a[o] == 10-s)
+ s=s+1
+ end
+end
+a1, u = nil
+assert(next(a) ~= nil)
+collectgarbage()
+assert(s==11)
+collectgarbage()
+assert(next(a) == nil) -- finalized keys are removed in two cycles
+
+
+-- __gc x weak tables
+local u = newproxy(true)
+setmetatable(getmetatable(u), {__mode = "v"})
+getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen
+collectgarbage()
+
+local u = newproxy(true)
+local m = getmetatable(u)
+m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"});
+m.__gc = function (o)
+ assert(next(getmetatable(o).x) == nil)
+ m = 10
+end
+u, m = nil
+collectgarbage()
+assert(m==10)
+
+
+-- errors during collection
+u = newproxy(true)
+getmetatable(u).__gc = function () error "!!!" end
+u = nil
+assert(not pcall(collectgarbage))
+
+
+if not rawget(_G, "_soft") then
+ print("deep structures")
+ local a = {}
+ for i = 1,200000 do
+ a = {next = a}
+ end
+ collectgarbage()
+end
+
+-- create many threads with self-references and open upvalues
+local thread_id = 0
+local threads = {}
+
+function fn(thread)
+ local x = {}
+ threads[thread_id] = function()
+ thread = x
+ end
+ coroutine.yield()
+end
+
+while thread_id < 1000 do
+ local thread = coroutine.create(fn)
+ coroutine.resume(thread, thread)
+ thread_id = thread_id + 1
+end
+
+
+
+-- create a userdata to be collected when state is closed
+do
+ local newproxy,assert,type,print,getmetatable =
+ newproxy,assert,type,print,getmetatable
+ local u = newproxy(true)
+ local tt = getmetatable(u)
+ ___Glob = {u} -- avoid udata being collected before program end
+ tt.__gc = function (o)
+ assert(getmetatable(o) == tt)
+ -- create new objects during GC
+ local a = 'xuxu'..(10+3)..'joao', {}
+ ___Glob = o -- ressurect object!
+ newproxy(o) -- creates a new one with same metatable
+ print(">>> closing state " .. "<<<\n")
+ end
+end
+
+-- create several udata to raise errors when collected while closing state
+do
+ local u = newproxy(true)
+ getmetatable(u).__gc = function (o) return o + 1 end
+ table.insert(___Glob, u) -- preserve udata until the end
+ for i = 1,10 do table.insert(___Glob, newproxy(u)) end
+end
+
+print('OK')
diff --git a/test/PUC-Lua-5.1-tests/libs/lib1.c b/test/PUC-Lua-5.1-tests/libs/lib1.c
new file mode 100644
index 0000000..22fe6de
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/libs/lib1.c
@@ -0,0 +1,40 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+#include "lauxlib.h"
+
+static int id (lua_State *L) {
+ return lua_gettop(L);
+}
+
+
+static const struct luaL_Reg funcs[] = {
+ {"id", id},
+ {NULL, NULL}
+};
+
+
+int anotherfunc (lua_State *L) {
+ lua_pushfstring(L, "%f%f\n", lua_tonumber(L, 1), lua_tonumber(L, 2));
+ return 1;
+}
+
+
+int luaopen_lib1_sub (lua_State *L) {
+ luaL_register(L, "lib1.sub", funcs + 1);
+ return 1;
+}
+
+
+int luaopen_lib1 (lua_State *L) {
+ luaL_register(L, "lib1", funcs);
+ return 1;
+}
+
+
diff --git a/test/PUC-Lua-5.1-tests/libs/lib11.c b/test/PUC-Lua-5.1-tests/libs/lib11.c
new file mode 100644
index 0000000..3efa3d3
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/libs/lib11.c
@@ -0,0 +1,18 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+
+
+int luaopen_lib1 (lua_State *L);
+
+int luaopen_lib11 (lua_State *L) {
+ return luaopen_lib1(L);
+}
+
+
diff --git a/test/PUC-Lua-5.1-tests/libs/lib2.c b/test/PUC-Lua-5.1-tests/libs/lib2.c
new file mode 100644
index 0000000..876a212
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/libs/lib2.c
@@ -0,0 +1,28 @@
+/*
+** compile with
+** gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+#include "lauxlib.h"
+
+static int id (lua_State *L) {
+ return lua_gettop(L);
+}
+
+
+static const struct luaL_Reg funcs[] = {
+ {"id", id},
+ {NULL, NULL}
+};
+
+
+int luaopen_lib2 (lua_State *L) {
+ luaL_register(L, "lib2", funcs);
+ lua_pushnumber(L, 0.5);
+ lua_setglobal(L, "x");
+ return 1;
+}
+
+
diff --git a/test/PUC-Lua-5.1-tests/libs/lib21.c b/test/PUC-Lua-5.1-tests/libs/lib21.c
new file mode 100644
index 0000000..167507f
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/libs/lib21.c
@@ -0,0 +1,18 @@
+/*
+** compile with
+** Linux: gcc -Wall -O2 -I.. -ansi -shared -o lib1.so lib1.c
+** Mac OS X: export MACOSX_DEPLOYMENT_TARGET=10.3
+** gcc -bundle -undefined dynamic_lookup -Wall -O2 -o lib1.so lib1.c
+*/
+
+
+#include "lua.h"
+
+
+int luaopen_lib2 (lua_State *L);
+
+int luaopen_lib21 (lua_State *L) {
+ return luaopen_lib2(L);
+}
+
+
diff --git a/test/PUC-Lua-5.1-tests/literals.lua b/test/PUC-Lua-5.1-tests/literals.lua
new file mode 100644
index 0000000..01d84d5
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/literals.lua
@@ -0,0 +1,176 @@
+print('testing scanner')
+
+local function dostring (x) return assert(loadstring(x))() end
+
+dostring("x = 'a\0a'")
+assert(x == 'a\0a' and string.len(x) == 3)
+
+-- escape sequences
+assert('\n\"\'\\' == [[
+
+"'\]])
+
+assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$"))
+
+-- assume ASCII just for tests:
+assert("\09912" == 'c12')
+assert("\99ab" == 'cab')
+assert("\099" == '\99')
+assert("\099\n" == 'c\10')
+assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo')
+
+assert(010 .. 020 .. -030 == "1020-30")
+
+-- long variable names
+
+var = string.rep('a', 15000)
+prog = string.format("%s = 5", var)
+dostring(prog)
+assert(_G[var] == 5)
+var = nil
+print('+')
+
+-- escapes --
+assert("\n\t" == [[
+
+ ]])
+assert([[
+
+ $debug]] == "\n $debug")
+assert([[ [ ]] ~= [[ ] ]])
+-- long strings --
+b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
+assert(string.len(b) == 960)
+prog = [=[
+print('+')
+
+a1 = [["isto e' um string com várias 'aspas'"]]
+a2 = "'aspas'"
+
+assert(string.find(a1, a2) == 31)
+print('+')
+
+a1 = [==[temp = [[um valor qualquer]]; ]==]
+assert(loadstring(a1))()
+assert(temp == 'um valor qualquer')
+-- long strings --
+b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
+assert(string.len(b) == 960)
+print('+')
+
+a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+00123456789012345678901234567890123456789123456789012345678901234567890123456789
+]]
+assert(string.len(a) == 1863)
+assert(string.sub(a, 1, 40) == string.sub(b, 1, 40))
+x = 1
+]=]
+
+print('+')
+x = nil
+dostring(prog)
+assert(x)
+
+prog = nil
+a = nil
+b = nil
+
+
+-- testing line ends
+prog = [[
+a = 1 -- a comment
+b = 2
+
+
+x = [=[
+hi
+]=]
+y = "\
+hello\r\n\
+"
+return debug.getinfo(1).currentline
+]]
+
+for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
+ local prog, nn = string.gsub(prog, "\n", n)
+ assert(dostring(prog) == nn)
+ assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
+end
+
+
+-- testing comments and strings with long brackets
+a = [==[]=]==]
+assert(a == "]=")
+
+a = [==[[===[[=[]]=][====[]]===]===]==]
+assert(a == "[===[[=[]]=][====[]]===]===")
+
+a = [====[[===[[=[]]=][====[]]===]===]====]
+assert(a == "[===[[=[]]=][====[]]===]===")
+
+a = [=[]]]]]]]]]=]
+assert(a == "]]]]]]]]")
+
+
+--[===[
+x y z [==[ blu foo
+]==
+]
+]=]==]
+error error]=]===]
+
+-- generate all strings of four of these chars
+local x = {"=", "[", "]", "\n"}
+local len = 4
+local function gen (c, n)
+ if n==0 then coroutine.yield(c)
+ else
+ for _, a in pairs(x) do
+ gen(c..a, n-1)
+ end
+ end
+end
+
+for s in coroutine.wrap(function () gen("", len) end) do
+ assert(s == loadstring("return [====[\n"..s.."]====]")())
+end
+
+
+-- testing decimal point locale
+if os.setlocale("pt_BR") or os.setlocale("ptb") then
+ assert(tonumber("3,4") == 3.4 and tonumber"3.4" == nil)
+ assert(assert(loadstring("return 3.4"))() == 3.4)
+ assert(assert(loadstring("return .4,3"))() == .4)
+ assert(assert(loadstring("return 4."))() == 4.)
+ assert(assert(loadstring("return 4.+.5"))() == 4.5)
+ local a,b = loadstring("return 4.5.")
+ assert(string.find(b, "'4%.5%.'"))
+ assert(os.setlocale("C"))
+else
+ (Message or print)(
+ '\a\n >>> pt_BR locale not available: skipping decimal point tests <<<\n\a')
+end
+
+
+print('OK')
diff --git a/test/PUC-Lua-5.1-tests/locals.lua b/test/PUC-Lua-5.1-tests/locals.lua
new file mode 100644
index 0000000..011645a
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/locals.lua
@@ -0,0 +1,127 @@
+print('testing local variables plus some extra stuff')
+
+do
+ local i = 10
+ do local i = 100; assert(i==100) end
+ do local i = 1000; assert(i==1000) end
+ assert(i == 10)
+ if i ~= 10 then
+ local i = 20
+ else
+ local i = 30
+ assert(i == 30)
+ end
+end
+
+
+
+f = nil
+
+local f
+x = 1
+
+a = nil
+loadstring('local a = {}')()
+assert(type(a) ~= 'table')
+
+function f (a)
+ local _1, _2, _3, _4, _5
+ local _6, _7, _8, _9, _10
+ local x = 3
+ local b = a
+ local c,d = a,b
+ if (d == b) then
+ local x = 'q'
+ x = b
+ assert(x == 2)
+ else
+ assert(nil)
+ end
+ assert(x == 3)
+ local f = 10
+end
+
+local b=10
+local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3
+
+
+assert(x == 1)
+
+f(2)
+assert(type(f) == 'function')
+
+
+-- testing globals ;-)
+do
+ local f = {}
+ local _G = _G
+ for i=1,10 do f[i] = function (x) A=A+1; return A, _G.getfenv(x) end end
+ A=10; assert(f[1]() == 11)
+ for i=1,10 do assert(setfenv(f[i], {A=i}) == f[i]) end
+ assert(f[3]() == 4 and A == 11)
+ local a,b = f[8](1)
+ assert(b.A == 9)
+ a,b = f[8](0)
+ assert(b.A == 11) -- `real' global
+ local g
+ local function f () assert(setfenv(2, {a='10'}) == g) end
+ g = function () f(); _G.assert(_G.getfenv(1).a == '10') end
+ g(); assert(getfenv(g).a == '10')
+end
+
+-- test for global table of loaded chunks
+local function foo (s)
+ return loadstring(s)
+end
+
+assert(getfenv(foo("")) == _G)
+local a = {loadstring = loadstring}
+setfenv(foo, a)
+assert(getfenv(foo("")) == _G)
+setfenv(0, a) -- change global environment
+assert(getfenv(foo("")) == a)
+setfenv(0, _G)
+
+
+-- testing limits for special instructions
+
+local a
+local p = 4
+for i=2,31 do
+ for j=-3,3 do
+ assert(loadstring(string.format([[local a=%s;a=a+
+ %s;
+ assert(a
+ ==2^%s)]], j, p-j, i))) ()
+ assert(loadstring(string.format([[local a=%s;
+ a=a-%s;
+ assert(a==-2^%s)]], -j, p-j, i))) ()
+ assert(loadstring(string.format([[local a,b=0,%s;
+ a=b-%s;
+ assert(a==-2^%s)]], -j, p-j, i))) ()
+ end
+ p =2*p
+end
+
+print'+'
+
+
+if rawget(_G, "querytab") then
+ -- testing clearing of dead elements from tables
+ collectgarbage("stop") -- stop GC
+ local a = {[{}] = 4, [3] = 0, alo = 1,
+ a1234567890123456789012345678901234567890 = 10}
+
+ local t = querytab(a)
+
+ for k,_ in pairs(a) do a[k] = nil end
+ collectgarbage() -- restore GC and collect dead fiels in `a'
+ for i=0,t-1 do
+ local k = querytab(a, i)
+ assert(k == nil or type(k) == 'number' or k == 'alo')
+ end
+end
+
+print('OK')
+
+return 5,f
diff --git a/test/PUC-Lua-5.1-tests/main.lua b/test/PUC-Lua-5.1-tests/main.lua
new file mode 100644
index 0000000..f520896
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/main.lua
@@ -0,0 +1,159 @@
+# testing special comment on first line
+
+print ("testing lua.c options")
+
+assert(os.execute() ~= 0) -- machine has a system command
+
+prog = os.tmpname()
+otherprog = os.tmpname()
+out = os.tmpname()
+
+do
+ local i = 0
+ while arg[i] do i=i-1 end
+ progname = '"'..arg[i+1]..'"'
+end
+print(progname)
+
+local prepfile = function (s, p)
+ p = p or prog
+ io.output(p)
+ io.write(s)
+ assert(io.close())
+end
+
+function checkout (s)
+ io.input(out)
+ local t = io.read("*a")
+ io.input():close()
+ assert(os.remove(out))
+ if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end
+ assert(s == t)
+ return t
+end
+
+function auxrun (...)
+ local s = string.format(...)
+ s = string.gsub(s, "lua", progname, 1)
+ return os.execute(s)
+end
+
+function RUN (...)
+ assert(auxrun(...) == 0)
+end
+
+function NoRun (...)
+ print("\n(the next error is expected by the test)")
+ assert(auxrun(...) ~= 0)
+end
+
+-- test 2 files
+prepfile("print(1); a=2")
+prepfile("print(a)", otherprog)
+RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out)
+checkout("1\n2\n2\n")
+
+local a = [[
+ assert(table.getn(arg) == 3 and arg[1] == 'a' and
+ arg[2] == 'b' and arg[3] == 'c')
+ assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == %s)
+ assert(arg[4] == nil and arg[-4] == nil)
+ local a, b, c = ...
+ assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
+]]
+a = string.format(a, progname)
+prepfile(a)
+RUN('lua "-e " -- %s a b c', prog)
+
+prepfile"assert(arg==nil)"
+prepfile("assert(arg)", otherprog)
+RUN("lua -l%s - < %s", prog, otherprog)
+
+prepfile""
+RUN("lua - < %s > %s", prog, out)
+checkout("")
+
+-- test many arguments
+prepfile[[print(({...})[30])]]
+RUN("lua %s %s > %s", prog, string.rep(" a", 30), out)
+checkout("a\n")
+
+RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
+checkout("1\n3\n")
+
+prepfile[[
+ print(
+1, a
+)
+]]
+RUN("lua - < %s > %s", prog, out)
+checkout("1\tnil\n")
+
+prepfile[[
+= (6*2-6) -- ===
+a
+= 10
+print(a)
+= a]]
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("6\n10\n10\n\n")
+
+prepfile("a = [[b\nc\nd\ne]]\n=a")
+print(prog)
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("b\nc\nd\ne\n\n")
+
+prompt = "alo"
+prepfile[[ --
+a = 2
+]]
+RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
+checkout(string.rep(prompt, 3).."\n")
+
+s = [=[ --
+function f ( x )
+ local a = [[
+xuxu
+]]
+ local b = "\
+xuxu\n"
+ if x == 11 then return 1 , 2 end --[[ test multiple returns ]]
+ return x + 1
+ --\\
+end
+=( f( 10 ) )
+assert( a == b )
+=f( 11 ) ]=]
+s = string.gsub(s, ' ', '\n\n')
+prepfile(s)
+RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
+checkout("11\n1\t2\n\n")
+
+prepfile[[#comment in 1st line without \n at the end]]
+RUN("lua %s", prog)
+
+prepfile("#comment with a binary file\n"..string.dump(loadstring("print(1)")))
+RUN("lua %s > %s", prog, out)
+checkout("1\n")
+
+prepfile("#comment with a binary file\r\n"..string.dump(loadstring("print(1)")))
+RUN("lua %s > %s", prog, out)
+checkout("1\n")
+
+-- close Lua with an open file
+prepfile(string.format([[io.output(%q); io.write('alo')]], out))
+RUN("lua %s", prog)
+checkout('alo')
+
+assert(os.remove(prog))
+assert(os.remove(otherprog))
+assert(not os.remove(out))
+
+RUN("lua -v")
+
+NoRun("lua -h")
+NoRun("lua -e")
+NoRun("lua -e a")
+NoRun("lua -f")
+
+print("OK")
diff --git a/test/PUC-Lua-5.1-tests/math.lua b/test/PUC-Lua-5.1-tests/math.lua
new file mode 100644
index 0000000..5076f38
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/math.lua
@@ -0,0 +1,208 @@
+print("testing numbers and math lib")
+
+do
+ local a,b,c = "2", " 3e0 ", " 10 "
+ assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0)
+ assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string')
+ assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ")
+ assert(c%a == 0 and a^b == 8)
+end
+
+
+do
+ local a,b = math.modf(3.5)
+ assert(a == 3 and b == 0.5)
+ assert(math.huge > 10e30)
+ assert(-math.huge < -10e30)
+end
+
+function f(...)
+ if select('#', ...) == 1 then
+ return (...)
+ else
+ return "***"
+ end
+end
+
+assert(tonumber{} == nil)
+assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
+ tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
+ tonumber'+1.' == 1)
+assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and
+ tonumber'1e' == nil and tonumber'1.0e+' == nil and
+ tonumber'.' == nil)
+assert(tonumber('-12') == -10-2)
+assert(tonumber('-1.2e2') == - - -120)
+assert(f(tonumber('1 a')) == nil)
+assert(f(tonumber('e1')) == nil)
+assert(f(tonumber('e 1')) == nil)
+assert(f(tonumber(' 3.4.5 ')) == nil)
+assert(f(tonumber('')) == nil)
+assert(f(tonumber('', 8)) == nil)
+assert(f(tonumber(' ')) == nil)
+assert(f(tonumber(' ', 9)) == nil)
+assert(f(tonumber('99', 8)) == nil)
+assert(tonumber(' 1010 ', 2) == 10)
+assert(tonumber('10', 36) == 36)
+--assert(tonumber('\n -10 \n', 36) == -36)
+--assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
+assert(tonumber('fFfa', 15) == nil)
+--assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
+assert(tonumber(string.rep('1', 32), 2) + 1 == 2^32)
+--assert(tonumber('-fffffFFFFF', 16)-1 == -2^40)
+assert(tonumber('ffffFFFF', 16)+1 == 2^32)
+
+assert(1.1 == 1.+.1)
+assert(100.0 == 1E2 and .01 == 1e-2)
+assert(1111111111111111-1111111111111110== 1000.00e-03)
+-- 1234567890123456
+assert(1.1 == '1.'+'.1')
+assert('1111111111111111'-'1111111111111110' == tonumber" +0.001e+3 \n\t")
+
+function eq (a,b,limit)
+ if not limit then limit = 10E-10 end
+ return math.abs(a-b) <= limit
+end
+
+assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31)
+
+assert(0.123456 > 0.123455)
+
+assert(tonumber('+1.23E30') == 1.23*10^30)
+
+-- testing order operators
+assert(not(1<1) and (1<2) and not(2<1))
+assert(not('a'<'a') and ('a'<'b') and not('b'<'a'))
+assert((1<=1) and (1<=2) and not(2<=1))
+assert(('a'<='a') and ('a'<='b') and not('b'<='a'))
+assert(not(1>1) and not(1>2) and (2>1))
+assert(not('a'>'a') and not('a'>'b') and ('b'>'a'))
+assert((1>=1) and not(1>=2) and (2>=1))
+assert(('a'>='a') and not('a'>='b') and ('b'>='a'))
+
+-- testing mod operator
+assert(-4%3 == 2)
+assert(4%-3 == -2)
+assert(math.pi - math.pi % 1 == 3)
+assert(math.pi - math.pi % 0.001 == 3.141)
+
+local function testbit(a, n)
+ return a/2^n % 2 >= 1
+end
+
+assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1))
+assert(eq(math.tan(math.pi/4), 1))
+assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0))
+assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and
+ eq(math.asin(1), math.pi/2))
+assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2))
+assert(math.abs(-10) == 10)
+assert(eq(math.atan2(1,0), math.pi/2))
+assert(math.ceil(4.5) == 5.0)
+assert(math.floor(4.5) == 4.0)
+assert(math.mod(10,3) == 1)
+assert(eq(math.sqrt(10)^2, 10))
+assert(eq(math.log10(2), math.log(2)/math.log(10)))
+assert(eq(math.exp(0), 1))
+assert(eq(math.sin(10), math.sin(10%(2*math.pi))))
+local v,e = math.frexp(math.pi)
+assert(eq(math.ldexp(v,e), math.pi))
+
+assert(eq(math.tanh(3.5), math.sinh(3.5)/math.cosh(3.5)))
+
+assert(tonumber(' 1.3e-2 ') == 1.3e-2)
+assert(tonumber(' -1.00000000000001 ') == -1.00000000000001)
+
+-- testing constant limits
+-- 2^23 = 8388608
+assert(8388609 + -8388609 == 0)
+assert(8388608 + -8388608 == 0)
+assert(8388607 + -8388607 == 0)
+
+if rawget(_G, "_soft") then return end
+
+f = io.tmpfile()
+assert(f)
+f:write("a = {")
+i = 1
+repeat
+ f:write("{", math.sin(i), ", ", math.cos(i), ", ", i/3, "},\n")
+ i=i+1
+until i > 1000
+f:write("}")
+f:seek("set", 0)
+assert(loadstring(f:read('*a')))()
+assert(f:close())
+
+assert(eq(a[300][1], math.sin(300)))
+assert(eq(a[600][1], math.sin(600)))
+assert(eq(a[500][2], math.cos(500)))
+assert(eq(a[800][2], math.cos(800)))
+assert(eq(a[200][3], 200/3))
+assert(eq(a[1000][3], 1000/3, 0.001))
+print('+')
+
+do -- testing NaN
+ local NaN = 10e500 - 10e400
+ assert(NaN ~= NaN)
+ assert(not (NaN < NaN))
+ assert(not (NaN <= NaN))
+ assert(not (NaN > NaN))
+ assert(not (NaN >= NaN))
+ assert(not (0 < NaN))
+ assert(not (NaN < 0))
+ local a = {}
+ assert(not pcall(function () a[NaN] = 1 end))
+ assert(a[NaN] == nil)
+ a[1] = 1
+ assert(not pcall(function () a[NaN] = 1 end))
+ assert(a[NaN] == nil)
+end
+
+require "checktable"
+stat(a)
+
+a = nil
+
+-- testing implicit convertions
+
+local a,b = '10', '20'
+assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20)
+assert(a == '10' and b == '20')
+
+
+math.randomseed(0)
+
+local i = 0
+local Max = 0
+local Min = 2
+repeat
+ local t = math.random()
+ Max = math.max(Max, t)
+ Min = math.min(Min, t)
+ i=i+1
+ flag = eq(Max, 1, 0.001) and eq(Min, 0, 0.001)
+until flag or i>10000
+assert(0 <= Min and Max<1)
+assert(flag);
+
+for i=1,10 do
+ local t = math.random(5)
+ assert(1 <= t and t <= 5)
+end
+
+i = 0
+Max = -200
+Min = 200
+repeat
+ local t = math.random(-10,0)
+ Max = math.max(Max, t)
+ Min = math.min(Min, t)
+ i=i+1
+ flag = (Max == 0 and Min == -10)
+until flag or i>10000
+assert(-10 <= Min and Max<=0)
+assert(flag);
+
+
+print('OK')
diff --git a/test/PUC-Lua-5.1-tests/nextvar.lua b/test/PUC-Lua-5.1-tests/nextvar.lua
new file mode 100644
index 0000000..7ceaa75
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/nextvar.lua
@@ -0,0 +1,396 @@
+print('testing tables, next, and for')
+
+local a = {}
+
+-- make sure table has lots of space in hash part
+for i=1,100 do a[i.."+"] = true end
+for i=1,100 do a[i.."+"] = nil end
+-- fill hash part with numeric indices testing size operator
+for i=1,100 do
+ a[i] = true
+ assert(#a == i)
+end
+
+
+if T then
+-- testing table sizes
+
+local l2 = math.log(2)
+local function log2 (x) return math.log(x)/l2 end
+
+local function mp2 (n) -- minimum power of 2 >= n
+ local mp = 2^math.ceil(log2(n))
+ assert(n == 0 or (mp/2 < n and n <= mp))
+ return mp
+end
+
+local function fb (n)
+ local r, nn = T.int2fb(n)
+ assert(r < 256)
+ return nn
+end
+
+-- test fb function
+local a = 1
+local lim = 2^30
+while a < lim do
+ local n = fb(a)
+ assert(a <= n and n <= a*1.125)
+ a = math.ceil(a*1.3)
+end
+
+
+local function check (t, na, nh)
+ local a, h = T.querytab(t)
+ if a ~= na or h ~= nh then
+ print(na, nh, a, h)
+ assert(nil)
+ end
+end
+
+-- testing constructor sizes
+local lim = 40
+local s = 'return {'
+for i=1,lim do
+ s = s..i..','
+ local s = s
+ for k=0,lim do
+ local t = loadstring(s..'}')()
+ assert(#t == i)
+ check(t, fb(i), mp2(k))
+ s = string.format('%sa%d=%d,', s, k, k)
+ end
+end
+
+
+-- tests with unknown number of elements
+local a = {}
+for i=1,lim do a[i] = i end -- build auxiliary table
+for k=0,lim do
+ local a = {unpack(a,1,k)}
+ assert(#a == k)
+ check(a, k, 0)
+ a = {1,2,3,unpack(a,1,k)}
+ check(a, k+3, 0)
+ assert(#a == k + 3)
+end
+
+
+print'+'
+
+-- testing tables dynamically built
+local lim = 130
+local a = {}; a[2] = 1; check(a, 0, 1)
+a = {}; a[0] = 1; check(a, 0, 1); a[2] = 1; check(a, 0, 2)
+a = {}; a[0] = 1; a[1] = 1; check(a, 1, 1)
+a = {}
+for i = 1,lim do
+ a[i] = 1
+ assert(#a == i)
+ check(a, mp2(i), 0)
+end
+
+a = {}
+for i = 1,lim do
+ a['a'..i] = 1
+ assert(#a == 0)
+ check(a, 0, mp2(i))
+end
+
+a = {}
+for i=1,16 do a[i] = i end
+check(a, 16, 0)
+for i=1,11 do a[i] = nil end
+for i=30,40 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 8)
+a[10] = 1
+for i=30,40 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 8)
+for i=1,14 do a[i] = nil end
+for i=30,50 do a[i] = nil end -- force a rehash (?)
+check(a, 0, 4)
+
+-- reverse filling
+for i=1,lim do
+ local a = {}
+ for i=i,1,-1 do a[i] = i end -- fill in reverse
+ check(a, mp2(i), 0)
+end
+
+-- size tests for vararg
+lim = 35
+function foo (n, ...)
+ local arg = {...}
+ check(arg, n, 0)
+ assert(select('#', ...) == n)
+ arg[n+1] = true
+ check(arg, mp2(n+1), 0)
+ arg.x = true
+ check(arg, mp2(n+1), 1)
+end
+local a = {}
+for i=1,lim do a[i] = true; foo(i, unpack(a)) end
+
+end
+
+
+-- test size operation on empty tables
+assert(#{} == 0)
+assert(#{nil} == 0)
+assert(#{nil, nil} == 0)
+assert(#{nil, nil, nil} == 0)
+assert(#{nil, nil, nil, nil} == 0)
+print'+'
+
+
+local nofind = {}
+
+a,b,c = 1,2,3
+a,b,c = nil
+
+local function find (name)
+ local n,v
+ while 1 do
+ n,v = next(_G, n)
+ if not n then return nofind end
+ assert(v ~= nil)
+ if n == name then return v end
+ end
+end
+
+local function find1 (name)
+ for n,v in pairs(_G) do
+ if n==name then return v end
+ end
+ return nil -- not found
+end
+
+do -- create 10000 new global variables
+ for i=1,10000 do _G[i] = i end
+end
+
+
+a = {x=90, y=8, z=23}
+assert(table.foreach(a, function(i,v) if i=='x' then return v end end) == 90)
+assert(table.foreach(a, function(i,v) if i=='a' then return v end end) == nil)
+table.foreach({}, error)
+
+table.foreachi({x=10, y=20}, error)
+local a = {n = 1}
+table.foreachi({n=3}, function (i, v)
+ assert(a.n == i and not v)
+ a.n=a.n+1
+end)
+a = {10,20,30,nil,50}
+table.foreachi(a, function (i,v) assert(a[i] == v) end)
+assert(table.foreachi({'a', 'b', 'c'}, function (i,v)
+ if i==2 then return v end
+ end) == 'b')
+
+
+assert(print==find("print") and print == find1("print"))
+assert(_G["print"]==find("print"))
+assert(assert==find1("assert"))
+assert(nofind==find("return"))
+assert(not find1("return"))
+_G["ret" .. "urn"] = nil
+assert(nofind==find("return"))
+_G["xxx"] = 1
+assert(xxx==find("xxx"))
+print('+')
+
+a = {}
+for i=0,10000 do
+ if math.mod(i,10) ~= 0 then
+ a['x'..i] = i
+ end
+end
+
+n = {n=0}
+for i,v in pairs(a) do
+ n.n = n.n+1
+ assert(i and v and a[i] == v)
+end
+assert(n.n == 9000)
+a = nil
+
+-- remove those 10000 new global variables
+for i=1,10000 do _G[i] = nil end
+
+do -- clear global table
+ local a = {}
+ local preserve = {io = 1, string = 1, debug = 1, os = 1,
+ coroutine = 1, table = 1, math = 1}
+ for n,v in pairs(_G) do a[n]=v end
+ for n,v in pairs(a) do
+ if not preserve[n] and type(v) ~= "function" and
+ not string.find(n, "^[%u_]") then
+ _G[n] = nil
+ end
+ collectgarbage()
+ end
+end
+
+local function foo ()
+ local getfenv, setfenv, assert, next =
+ getfenv, setfenv, assert, next
+ local n = {gl1=3}
+ setfenv(foo, n)
+ assert(getfenv(foo) == getfenv(1))
+ assert(getfenv(foo) == n)
+ assert(print == nil and gl1 == 3)
+ gl1 = nil
+ gl = 1
+ assert(n.gl == 1 and next(n, 'gl') == nil)
+end
+foo()
+
+print'+'
+
+local function checknext (a)
+ local b = {}
+ table.foreach(a, function (k,v) b[k] = v end)
+ for k,v in pairs(b) do assert(a[k] == v) end
+ for k,v in pairs(a) do assert(b[k] == v) end
+ b = {}
+ do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end
+ for k,v in pairs(b) do assert(a[k] == v) end
+ for k,v in pairs(a) do assert(b[k] == v) end
+end
+
+checknext{1,x=1,y=2,z=3}
+checknext{1,2,x=1,y=2,z=3}
+checknext{1,2,3,x=1,y=2,z=3}
+checknext{1,2,3,4,x=1,y=2,z=3}
+checknext{1,2,3,4,5,x=1,y=2,z=3}
+
+assert(table.getn{} == 0)
+assert(table.getn{[-1] = 2} == 0)
+assert(table.getn{1,2,3,nil,nil} == 3)
+for i=0,40 do
+ local a = {}
+ for j=1,i do a[j]=j end
+ assert(table.getn(a) == i)
+end
+
+
+assert(table.maxn{} == 0)
+assert(table.maxn{["1000"] = true} == 0)
+assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5)
+assert(table.maxn{[1000] = true} == 1000)
+assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi)
+
+
+-- int overflow
+a = {}
+for i=0,50 do a[math.pow(2,i)] = true end
+assert(a[table.getn(a)])
+
+print("+")
+
+
+-- erasing values
+local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3,
+ [100.3] = 4, [4] = 5}
+
+local n = 0
+for k, v in pairs( t ) do
+ n = n+1
+ assert(t[k] == v)
+ t[k] = nil
+ collectgarbage()
+ assert(t[k] == nil)
+end
+assert(n == 5)
+
+
+local function test (a)
+ table.insert(a, 10); table.insert(a, 2, 20);
+ table.insert(a, 1, -1); table.insert(a, 40);
+ table.insert(a, table.getn(a)+1, 50)
+ table.insert(a, 2, -2)
+ assert(table.remove(a,1) == -1)
+ assert(table.remove(a,1) == -2)
+ assert(table.remove(a,1) == 10)
+ assert(table.remove(a,1) == 20)
+ assert(table.remove(a,1) == 40)
+ assert(table.remove(a,1) == 50)
+ assert(table.remove(a,1) == nil)
+end
+
+a = {n=0, [-7] = "ban"}
+test(a)
+assert(a.n == 0 and a[-7] == "ban")
+
+a = {[-7] = "ban"};
+test(a)
+assert(a.n == nil and table.getn(a) == 0 and a[-7] == "ban")
+
+
+table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
+assert(table.remove(a) == 10)
+assert(table.remove(a) == 20)
+assert(table.remove(a) == -1)
+
+a = {'c', 'd'}
+table.insert(a, 3, 'a')
+table.insert(a, 'b')
+assert(table.remove(a, 1) == 'c')
+assert(table.remove(a, 1) == 'd')
+assert(table.remove(a, 1) == 'a')
+assert(table.remove(a, 1) == 'b')
+assert(table.getn(a) == 0 and a.n == nil)
+print("+")
+
+a = {}
+for i=1,1000 do
+ a[i] = i; a[i-1] = nil
+end
+assert(next(a,nil) == 1000 and next(a,1000) == nil)
+
+assert(next({}) == nil)
+assert(next({}, nil) == nil)
+
+for a,b in pairs{} do error"not here" end
+for i=1,0 do error'not here' end
+for i=0,1,-1 do error'not here' end
+a = nil; for i=1,1 do assert(not a); a=1 end; assert(a)
+a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a)
+
+a = 0; for i=0, 1, 0.1 do a=a+1 end; assert(a==11)
+-- precision problems
+--a = 0; for i=1, 0, -0.01 do a=a+1 end; assert(a==101)
+a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10)
+a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1)
+a = 0; for i=1e10, 1e10, -1 do a=a+1 end; assert(a==1)
+a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0)
+a = 0; for i=99999, 1e5, -1 do a=a+1 end; assert(a==0)
+a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1)
+
+-- conversion
+a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5)
+
+
+collectgarbage()
+
+
+-- testing generic 'for'
+
+local function f (n, p)
+ local t = {}; for i=1,p do t[i] = i*10 end
+ return function (_,n)
+ if n > 0 then
+ n = n-1
+ return n, unpack(t)
+ end
+ end, nil, n
+end
+
+local x = 0
+for n,a,b,c,d in f(5,3) do
+ x = x+1
+ assert(a == 10 and b == 20 and c == 30 and d == nil)
+end
+assert(x == 5)
+
+print"OK"
diff --git a/test/PUC-Lua-5.1-tests/pm.lua b/test/PUC-Lua-5.1-tests/pm.lua
new file mode 100644
index 0000000..fa125dc
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/pm.lua
@@ -0,0 +1,273 @@
+print('testing pattern matching')
+
+function f(s, p)
+ local i,e = string.find(s, p)
+ if i then return string.sub(s, i, e) end
+end
+
+function f1(s, p)
+ p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
+ p = string.gsub(p, "^(^?)", "%1()", 1)
+ p = string.gsub(p, "($?)$", "()%1", 1)
+ local t = {string.match(s, p)}
+ return string.sub(s, t[1], t[#t] - 1)
+end
+
+a,b = string.find('', '') -- empty patterns are tricky
+assert(a == 1 and b == 0);
+a,b = string.find('alo', '')
+assert(a == 1 and b == 0)
+a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position
+assert(a == 1 and b == 1)
+a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle
+assert(a == 5 and b == 7)
+a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle
+assert(a == 9 and b == 11)
+a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
+assert(a == 9 and b == 11);
+a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position
+assert(a == 11 and b == 11)
+assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending
+assert(string.find('', '\0') == nil)
+assert(string.find('alo123alo', '12') == 4)
+assert(string.find('alo123alo', '^12') == nil)
+
+assert(f('aloALO', '%l*') == 'alo')
+assert(f('aLo_ALO', '%a*') == 'aLo')
+
+assert(f('aaab', 'a*') == 'aaa');
+assert(f('aaa', '^.*$') == 'aaa');
+assert(f('aaa', 'b*') == '');
+assert(f('aaa', 'ab*a') == 'aa')
+assert(f('aba', 'ab*a') == 'aba')
+assert(f('aaab', 'a+') == 'aaa')
+assert(f('aaa', '^.+$') == 'aaa')
+assert(f('aaa', 'b+') == nil)
+assert(f('aaa', 'ab+a') == nil)
+assert(f('aba', 'ab+a') == 'aba')
+assert(f('a$a', '.$') == 'a')
+assert(f('a$a', '.%$') == 'a$')
+assert(f('a$a', '.$.') == 'a$a')
+assert(f('a$a', '$$') == nil)
+assert(f('a$b', 'a$') == nil)
+assert(f('a$a', '$') == '')
+assert(f('', 'b*') == '')
+assert(f('aaa', 'bb*') == nil)
+assert(f('aaab', 'a-') == '')
+assert(f('aaa', '^.-$') == 'aaa')
+assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab')
+assert(f('aabaaabaaabaaaba', 'b.-b') == 'baaab')
+assert(f('alo xo', '.o$') == 'xo')
+assert(f(' \n isto é assim', '%S%S*') == 'isto')
+assert(f(' \n isto é assim', '%S*$') == 'assim')
+assert(f(' \n isto é assim', '[a-z]*$') == 'assim')
+assert(f('um caracter ? extra', '[^%sa-z]') == '?')
+assert(f('', 'a?') == '')
+assert(f('á', 'á?') == 'á')
+assert(f('ábl', 'á?b?l?') == 'ábl')
+assert(f(' ábl', 'á?b?l?') == '')
+assert(f('aa', '^aa?a?a') == 'aa')
+assert(f(']]]áb', '[^]]') == 'á')
+assert(f("0alo alo", "%x*") == "0a")
+assert(f("alo alo", "%C+") == "alo alo")
+print('+')
+
+assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
+assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
+assert(f1('=======', '^(=*)=%1$') == '=======')
+assert(string.match('==========', '^([=]*)=%1$') == nil)
+
+local function range (i, j)
+ if i <= j then
+ return i, range(i+1, j)
+ end
+end
+
+local abc = string.char(range(0, 255));
+
+assert(string.len(abc) == 256)
+
+function strset (p)
+ local res = {s=''}
+ string.gsub(abc, p, function (c) res.s = res.s .. c end)
+ return res.s
+end;
+
+assert(string.len(strset('[\200-\210]')) == 11)
+
+assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz")
+assert(strset('[a-z%d]') == strset('[%da-uu-z]'))
+assert(strset('[a-]') == "-a")
+assert(strset('[^%W]') == strset('[%w]'))
+assert(strset('[]%%]') == '%]')
+assert(strset('[a%-z]') == '-az')
+assert(strset('[%^%[%-a%]%-b]') == '-[]^ab')
+assert(strset('%Z') == strset('[\1-\255]'))
+assert(strset('.') == strset('[\1-\255%z]'))
+print('+');
+
+assert(string.match("alo xyzK", "(%w+)K") == "xyz")
+assert(string.match("254 K", "(%d*)K") == "")
+assert(string.match("alo ", "(%w*)$") == "")
+assert(string.match("alo ", "(%w+)$") == nil)
+assert(string.find("(álo)", "%(á") == 1)
+local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$")
+assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil)
+a, b, c, d = string.match('0123456789', '(.+(.?)())')
+assert(a == '0123456789' and b == '' and c == 11 and d == nil)
+print('+')
+
+assert(string.gsub('ülo ülo', 'ü', 'x') == 'xlo xlo')
+assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim
+assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim
+assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ')
+t = "abç d"
+a, b = string.gsub(t, '(.)', '%1@')
+assert('@'..a == string.gsub(t, '', '@') and b == 5)
+a, b = string.gsub('abçd', '(.)', '%0@', 2)
+assert(a == 'a at b@çd' and b == 2)
+assert(string.gsub('alo alo', '()[al]', '%1') == '12o 56o')
+assert(string.gsub("abc=xyz", "(%w*)(%p)(%w+)", "%3%2%1-%0") ==
+ "xyz=abc-abc=xyz")
+assert(string.gsub("abc", "%w", "%1%0") == "aabbcc")
+assert(string.gsub("abc", "%w+", "%0%1") == "abcabc")
+assert(string.gsub('áéí', '$', '\0óú') == 'áéí\0óú')
+assert(string.gsub('', '^', 'r') == 'r')
+assert(string.gsub('', '$', 'r') == 'r')
+print('+')
+
+assert(string.gsub("um (dois) tres (quatro)", "(%(%w+%))", string.upper) ==
+ "um (DOIS) tres (QUATRO)")
+
+do
+ local function setglobal (n,v) rawset(_G, n, v) end
+ string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal)
+ assert(_G.a=="roberto" and _G.roberto=="a")
+end
+
+function f(a,b) return string.gsub(a,'.',b) end
+assert(string.gsub("trocar tudo em |teste|b| é |beleza|al|", "|([^|]*)|([^|]*)|", f) ==
+ "trocar tudo em bbbbb é alalalalalal")
+
+local function dostring (s) return loadstring(s)() or "" end
+assert(string.gsub("alo $a=1$ novamente $return a$", "$([^$]*)%$", dostring) ==
+ "alo novamente 1")
+
+x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$",
+ "$([^$]*)%$", dostring)
+assert(x == ' assim vai para ALO')
+
+t = {}
+s = 'a alo jose joao'
+r = string.gsub(s, '()(%w+)()', function (a,w,b)
+ assert(string.len(w) == b-a);
+ t[a] = b-a;
+ end)
+assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
+
+
+function isbalanced (s)
+ return string.find(string.gsub(s, "%b()", ""), "[()]") == nil
+end
+
+assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a"))
+assert(not isbalanced("(9 ((8) 7) a b (\0 c) a"))
+assert(string.gsub("alo 'oi' alo", "%b''", '"') == 'alo " alo')
+
+
+local t = {"apple", "orange", "lime"; n=0}
+assert(string.gsub("x and x and x", "x", function () t.n=t.n+1; return t[t.n] end)
+ == "apple and orange and lime")
+
+t = {n=0}
+string.gsub("first second word", "%w%w*", function (w) t.n=t.n+1; t[t.n] = w end)
+assert(t[1] == "first" and t[2] == "second" and t[3] == "word" and t.n == 3)
+
+t = {n=0}
+assert(string.gsub("first second word", "%w+",
+ function (w) t.n=t.n+1; t[t.n] = w end, 2) == "first second word")
+assert(t[1] == "first" and t[2] == "second" and t[3] == nil)
+
+assert(not pcall(string.gsub, "alo", "(.", print))
+assert(not pcall(string.gsub, "alo", ".)", print))
+assert(not pcall(string.gsub, "alo", "(.", {}))
+assert(not pcall(string.gsub, "alo", "(.)", "%2"))
+assert(not pcall(string.gsub, "alo", "(%1)", "a"))
+assert(not pcall(string.gsub, "alo", "(%0)", "a"))
+
+-- big strings
+local a = string.rep('a', 300000)
+assert(string.find(a, '^a*.?$'))
+assert(not string.find(a, '^a*.?b$'))
+assert(string.find(a, '^a-.?$'))
+
+-- deep nest of gsubs
+function rev (s)
+ return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end)
+end
+
+local x = string.rep('012345', 10)
+assert(rev(rev(x)) == x)
+
+
+-- gsub with tables
+assert(string.gsub("alo alo", ".", {}) == "alo alo")
+assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
+assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
+assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
+
+assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo")
+
+t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
+assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
+
+
+-- tests for gmatch
+assert(string.gfind == string.gmatch)
+local a = 0
+for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
+assert(a==6)
+
+t = {n=0}
+for w in string.gmatch("first second word", "%w+") do
+ t.n=t.n+1; t[t.n] = w
+end
+assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
+
+t = {3, 6, 9}
+for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
+ assert(i == table.remove(t, 1))
+end
+assert(table.getn(t) == 0)
+
+t = {}
+for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
+ t[i] = j
+end
+a = 0
+for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
+assert(a == 3)
+
+
+-- tests for `%f' (`frontiers')
+
+assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
+assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[")
+assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3")
+assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.")
+assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction")
+assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.")
+
+local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]")
+assert(i == 2 and e == 5)
+local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])")
+assert(k == 'alo ')
+
+local a = {1, 5, 9, 14, 17,}
+for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do
+ assert(table.remove(a, 1) == k)
+end
+assert(table.getn(a) == 0)
+
+
+print('OK')
diff --git a/test/PUC-Lua-5.1-tests/sort.lua b/test/PUC-Lua-5.1-tests/sort.lua
new file mode 100644
index 0000000..6fccd49
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/sort.lua
@@ -0,0 +1,74 @@
+print"testing sort"
+
+
+function check (a, f)
+ f = f or function (x,y) return x<y end;
+ for n=table.getn(a),2,-1 do
+ assert(not f(a[n], a[n-1]))
+ end
+end
+
+a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"}
+
+table.sort(a)
+check(a)
+
+limit = 30000
+if rawget(_G, "_soft") then limit = 5000 end
+
+a = {}
+for i=1,limit do
+ a[i] = math.random()
+end
+
+local x = os.clock()
+table.sort(a)
+print(string.format("Sorting %d elements in %.2f sec.", limit, os.clock()-x))
+check(a)
+
+x = os.clock()
+table.sort(a)
+print(string.format("Re-sorting %d elements in %.2f sec.", limit, os.clock()-x))
+check(a)
+
+a = {}
+for i=1,limit do
+ a[i] = math.random()
+end
+
+x = os.clock(); i=0
+table.sort(a, function(x,y) i=i+1; return y<x end)
+print(string.format("Invert-sorting other %d elements in %.2f sec., with %i comparisons",
+ limit, os.clock()-x, i))
+check(a, function(x,y) return y<x end)
+
+
+table.sort{} -- empty array
+
+for i=1,limit do a[i] = false end
+x = os.clock();
+table.sort(a, function(x,y) return nil end)
+print(string.format("Sorting %d equal elements in %.2f sec.", limit, os.clock()-x))
+check(a, function(x,y) return nil end)
+for i,v in pairs(a) do assert(not v or i=='n' and v==limit) end
+
+a = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
+table.sort(a)
+check(a)
+
+table.sort(a, function (x, y)
+ loadstring(string.format("a[%q] = ''", x))()
+ collectgarbage()
+ return x<y
+ end)
+
+
+tt = {__lt = function (a,b) return a.val < b.val end}
+a = {}
+for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end
+table.sort(a)
+check(a, tt.__lt)
+check(a)
+
+print"OK"
diff --git a/test/PUC-Lua-5.1-tests/strings.lua b/test/PUC-Lua-5.1-tests/strings.lua
new file mode 100644
index 0000000..237dbad
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/strings.lua
@@ -0,0 +1,176 @@
+print('testing strings and string library')
+
+assert('alo' < 'alo1')
+assert('' < 'a')
+assert('alo\0alo' < 'alo\0b')
+assert('alo\0alo\0\0' > 'alo\0alo\0')
+assert('alo' < 'alo\0')
+assert('alo\0' > 'alo')
+assert('\0' < '\1')
+assert('\0\0' < '\0\1')
+assert('\1\0a\0a' <= '\1\0a\0a')
+assert(not ('\1\0a\0b' <= '\1\0a\0a'))
+assert('\0\0\0' < '\0\0\0\0')
+assert(not('\0\0\0\0' < '\0\0\0'))
+assert('\0\0\0' <= '\0\0\0\0')
+assert(not('\0\0\0\0' <= '\0\0\0'))
+assert('\0\0\0' <= '\0\0\0')
+assert('\0\0\0' >= '\0\0\0')
+assert(not ('\0\0b' < '\0\0a\0'))
+print('+')
+
+assert(string.sub("123456789",2,4) == "234")
+assert(string.sub("123456789",7) == "789")
+assert(string.sub("123456789",7,6) == "")
+assert(string.sub("123456789",7,7) == "7")
+assert(string.sub("123456789",0,0) == "")
+assert(string.sub("123456789",-10,10) == "123456789")
+assert(string.sub("123456789",1,9) == "123456789")
+assert(string.sub("123456789",-10,-20) == "")
+assert(string.sub("123456789",-1) == "9")
+assert(string.sub("123456789",-4) == "6789")
+assert(string.sub("123456789",-6, -4) == "456")
+assert(string.sub("\000123456789",3,5) == "234")
+assert(("\000123456789"):sub(8) == "789")
+print('+')
+
+assert(string.find("123456789", "345") == 3)
+a,b = string.find("123456789", "345")
+assert(string.sub("123456789", a, b) == "345")
+assert(string.find("1234567890123456789", "345", 3) == 3)
+assert(string.find("1234567890123456789", "345", 4) == 13)
+assert(string.find("1234567890123456789", "346", 4) == nil)
+assert(string.find("1234567890123456789", ".45", -9) == 13)
+assert(string.find("abcdefg", "\0", 5, 1) == nil)
+assert(string.find("", "") == 1)
+assert(string.find('', 'aaa', 1) == nil)
+assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
+print('+')
+
+assert(string.len("") == 0)
+assert(string.len("\0\0\0") == 3)
+assert(string.len("1234567890") == 10)
+
+assert(#"" == 0)
+assert(#"\0\0\0" == 3)
+assert(#"1234567890" == 10)
+
+assert(string.byte("a") == 97)
+assert(string.byte("á") > 127)
+assert(string.byte(string.char(255)) == 255)
+assert(string.byte(string.char(0)) == 0)
+assert(string.byte("\0") == 0)
+assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
+assert(string.byte("ba", 2) == 97)
+assert(string.byte("\n\n", 2, -1) == 10)
+assert(string.byte("\n\n", 2, 2) == 10)
+assert(string.byte("") == nil)
+assert(string.byte("hi", -3) == nil)
+assert(string.byte("hi", 3) == nil)
+assert(string.byte("hi", 9, 10) == nil)
+assert(string.byte("hi", 2, 1) == nil)
+assert(string.char() == "")
+assert(string.char(0, 255, 0) == "\0\255\0")
+assert(string.char(0, string.byte("á"), 0) == "\0á\0")
+assert(string.char(string.byte("ál\0óu", 1, -1)) == "ál\0óu")
+assert(string.char(string.byte("ál\0óu", 1, 0)) == "")
+assert(string.char(string.byte("ál\0óu", -10, 100)) == "ál\0óu")
+print('+')
+
+assert(string.upper("ab\0c") == "AB\0C")
+assert(string.lower("\0ABCc%$") == "\0abcc%$")
+assert(string.rep('teste', 0) == '')
+assert(string.rep('tés\00tê', 2) == 'tés\0têtés\000tê')
+assert(string.rep('', 10) == '')
+
+assert(string.reverse"" == "")
+assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
+assert(string.reverse"\0001234" == "4321\0")
+
+for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
+
+assert(type(tostring(nil)) == 'string')
+assert(type(tostring(12)) == 'string')
+assert(''..12 == '12' and type(12 .. '') == 'string')
+assert(string.find(tostring{}, 'table:'))
+assert(string.find(tostring(print), 'function:'))
+assert(tostring(1234567890123) == '1234567890123')
+assert(#tostring('\0') == 1)
+assert(tostring(true) == "true")
+assert(tostring(false) == "false")
+print('+')
+
+x = '"ílo"\n\\'
+assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
+assert(string.format('%q', "\0") == [["\000"]])
+assert(string.format("\0%c\0%c%x\0", string.byte("á"), string.byte("b"), 140) ==
+ "\0á\0b8c\0")
+assert(string.format('') == "")
+assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
+ string.format("%c%c%c%c", 34, 48, 90, 100))
+assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
+assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
+assert(tonumber(string.format("%f", 10.3)) == 10.3)
+x = string.format('"%-50s"', 'a')
+assert(#x == 52)
+assert(string.sub(x, 1, 4) == '"a ')
+
+assert(string.format("-%.20s.20s", string.rep("%", 2000)) == "-"..string.rep("%", 20)..".20s")
+assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
+ string.format("%q", "-"..string.rep("%", 2000)..".20s"))
+
+
+-- longest number that can be formated
+assert(string.len(string.format('%99.99f', -1e308)) >= 100)
+
+assert(loadstring("return 1\n--comentário sem EOL no final")() == 1)
+
+
+assert(table.concat{} == "")
+assert(table.concat({}, 'x') == "")
+assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
+local a = {}; for i=1,3000 do a[i] = "xuxu" end
+assert(table.concat(a, "123").."123" == string.rep("xuxu123", 3000))
+assert(table.concat(a, "b", 20, 20) == "xuxu")
+assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
+assert(table.concat(a, "", 22, 21) == "")
+assert(table.concat(a, "3", 2999) == "xuxu3xuxu")
+
+a = {"a","b","c"}
+assert(table.concat(a, ",", 1, 0) == "")
+assert(table.concat(a, ",", 1, 1) == "a")
+assert(table.concat(a, ",", 1, 2) == "a,b")
+assert(table.concat(a, ",", 2) == "b,c")
+assert(table.concat(a, ",", 3) == "c")
+assert(table.concat(a, ",", 4) == "")
+
+local locales = { "ptb", "ISO-8859-1", "pt_BR" }
+local function trylocale (w)
+ for _, l in ipairs(locales) do
+ if os.setlocale(l, w) then return true end
+ end
+ return false
+end
+
+if not trylocale("collate") then
+ print("locale not supported")
+else
+ assert("alo" < "álo" and "álo" < "amo")
+end
+
+if not trylocale("ctype") then
+ print("locale not supported")
+else
+ assert(string.gsub("áéíóú", "%a", "x") == "xxxxx")
+ assert(string.gsub("áÁéÉ", "%l", "x") == "xÁxÉ")
+ assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
+ assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
+end
+
+os.setlocale("C")
+assert(os.setlocale() == 'C')
+assert(os.setlocale(nil, "numeric") == 'C')
+
+print('OK')
+
+
diff --git a/test/PUC-Lua-5.1-tests/vararg.lua b/test/PUC-Lua-5.1-tests/vararg.lua
new file mode 100644
index 0000000..ae068fa
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/vararg.lua
@@ -0,0 +1,126 @@
+print('testing vararg')
+
+_G.arg = nil
+
+function f(a, ...)
+ assert(type(arg) == 'table')
+ assert(type(arg.n) == 'number')
+ for i=1,arg.n do assert(a[i]==arg[i]) end
+ return arg.n
+end
+
+function c12 (...)
+ assert(arg == nil)
+ local x = {...}; x.n = table.getn(x)
+ local res = (x.n==2 and x[1] == 1 and x[2] == 2)
+ if res then res = 55 end
+ return res, 2
+end
+
+function vararg (...) return arg end
+
+local call = function (f, args) return f(unpack(args, 1, args.n)) end
+
+assert(f() == 0)
+assert(f({1,2,3}, 1, 2, 3) == 3)
+assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5)
+
+assert(c12(1,2)==55)
+a,b = assert(call(c12, {1,2}))
+assert(a == 55 and b == 2)
+a = call(c12, {1,2;n=2})
+assert(a == 55 and b == 2)
+a = call(c12, {1,2;n=1})
+assert(not a)
+assert(c12(1,2,3) == false)
+local a = vararg(call(next, {_G,nil;n=2}))
+local b,c = next(_G)
+assert(a[1] == b and a[2] == c and a.n == 2)
+a = vararg(call(call, {c12, {1,2}}))
+assert(a.n == 2 and a[1] == 55 and a[2] == 2)
+a = call(print, {'+'})
+assert(a == nil)
+
+local t = {1, 10}
+function t:f (...) return self[arg[1]]+arg.n end
+assert(t:f(1,4) == 3 and t:f(2) == 11)
+print('+')
+
+lim = 20
+local i, a = 1, {}
+while i <= lim do a[i] = i+0.3; i=i+1 end
+
+function f(a, b, c, d, ...)
+ local more = {...}
+ assert(a == 1.3 and more[1] == 5.3 and
+ more[lim-4] == lim+0.3 and not more[lim-3])
+end
+
+function g(a,b,c)
+ assert(a == 1.3 and b == 2.3 and c == 3.3)
+end
+
+call(f, a)
+call(g, a)
+
+a = {}
+i = 1
+while i <= lim do a[i] = i; i=i+1 end
+assert(call(math.max, a) == lim)
+
+print("+")
+
+
+-- new-style varargs
+
+function oneless (a, ...) return ... end
+
+function f (n, a, ...)
+ local b
+ assert(arg == nil)
+ if n == 0 then
+ local b, c, d = ...
+ return a, b, c, d, oneless(oneless(oneless(...)))
+ else
+ n, b, a = n-1, ..., a
+ assert(b == ...)
+ return f(n, a, ...)
+ end
+end
+
+a,b,c,d,e = assert(f(10,5,4,3,2,1))
+assert(a==5 and b==4 and c==3 and d==2 and e==1)
+
+a,b,c,d,e = f(4)
+assert(a==nil and b==nil and c==nil and d==nil and e==nil)
+
+
+-- varargs for main chunks
+f = loadstring[[ return {...} ]]
+x = f(2,3)
+assert(x[1] == 2 and x[2] == 3 and x[3] == nil)
+
+
+f = loadstring[[
+ local x = {...}
+ for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
+ assert(x[select('#', ...)+1] == nil)
+ return true
+]]
+
+assert(f("a", "b", nil, {}, assert))
+assert(f())
+
+a = {select(3, unpack{10,20,30,40})}
+assert(table.getn(a) == 2 and a[1] == 30 and a[2] == 40)
+a = {select(1)}
+assert(next(a) == nil)
+a = {select(-1, 3, 5, 7)}
+assert(a[1] == 7 and a[2] == nil)
+a = {select(-2, 3, 5, 7)}
+assert(a[1] == 5 and a[2] == 7 and a[3] == nil)
+pcall(select, 10000)
+pcall(select, -10000)
+
+print('OK')
+
diff --git a/test/PUC-Lua-5.1-tests/verybig.lua b/test/PUC-Lua-5.1-tests/verybig.lua
new file mode 100644
index 0000000..59e0142
--- /dev/null
+++ b/test/PUC-Lua-5.1-tests/verybig.lua
@@ -0,0 +1,100 @@
+if rawget(_G, "_soft") then return 10 end
+
+print "testing large programs (>64k)"
+
+-- template to create a very big test file
+prog = [[$
+
+local a,b
+
+b = {$1$
+ b30009 = 65534,
+ b30010 = 65535,
+ b30011 = 65536,
+ b30012 = 65537,
+ b30013 = 16777214,
+ b30014 = 16777215,
+ b30015 = 16777216,
+ b30016 = 16777217,
+ b30017 = 4294967294,
+ b30018 = 4294967295,
+ b30019 = 4294967296,
+ b30020 = 4294967297,
+ b30021 = -65534,
+ b30022 = -65535,
+ b30023 = -65536,
+ b30024 = -4294967297,
+ b30025 = 15012.5,
+ $2$
+};
+
+assert(b.a50008 == 25004 and b["a11"] == 5.5)
+assert(b.a33007 == 16503.5 and b.a50009 == 25004.5)
+assert(b["b"..30024] == -4294967297)
+
+function b:xxx (a,b) return a+b end
+assert(b:xxx(10, 12) == 22) -- pushself with non-constant index
+b.xxx = nil
+
+s = 0; n=0
+for a,b in pairs(b) do s=s+b; n=n+1 end
+assert(s==13977183656.5 and n==70001)
+
+require "checktable"
+stat(b)
+
+a = nil; b = nil
+print'+'
+
+function f(x) b=x end
+
+a = f{$3$} or 10
+
+assert(a==10)
+assert(b[1] == "a10" and b[2] == 5 and b[table.getn(b)-1] == "a50009")
+
+
+function xxxx (x) return b[x] end
+
+assert(xxxx(3) == "a11")
+
+a = nil; b=nil
+xxxx = nil
+
+return 10
+
+]]
+
+-- functions to fill in the $n$
+F = {
+function () -- $1$
+ for i=10,50009 do
+ io.write('a', i, ' = ', 5+((i-10)/2), ',\n')
+ end
+end,
+
+function () -- $2$
+ for i=30026,50009 do
+ io.write('b', i, ' = ', 15013+((i-30026)/2), ',\n')
+ end
+end,
+
+function () -- $3$
+ for i=10,50009 do
+ io.write('"a', i, '", ', 5+((i-10)/2), ',\n')
+ end
+end,
+}
+
+file = os.tmpname()
+io.output(file)
+for s in string.gmatch(prog, "$([^$]+)") do
+ local n = tonumber(s)
+ if not n then io.write(s) else F[n]() end
+end
+io.close()
+result = dofile(file)
+assert(os.remove(file))
+print'OK'
+return result
+
--
2.28.0
More information about the Tarantool-patches
mailing list