print('-------- simple upvalues tests --------')
local function simpleupvalues()
	function test()
		local x = 5
		function f()
			x = x + 1
			return x
		end

		function g()
			x = x - 1
			return x
		end

		print(f())
		print(g())
		return f, g
	end

	f1, g1 = test()
	print("f1()=", f1())
	print("g1()=", g1())

	f2, g2 = test()
	print("f2()=", f2())
	print("g2()=", g2())

	print("g1()=", g1())
	print("f1()=", f1())
end

print('simplevalues result:', pcall(simpleupvalues))


-- The point of this test is that when an upvalue is created, it may
-- need to be inserted in the middle of the list, rather than always
-- appended at the end. Otherwise, it may not be found when it is
-- needed by another closure.
print('----------- upvalued in middle ------------')
local function middleupvaluestest()
	local function test()
		local x = 3
		local y = 5
		local z = 7

		local function f()
			print("y=", y)
		end

		local function g()
			print("z=", z)
		end

		local function h()
			print("x=", x)
		end

		local function setter(x1, y1, z1)
			x = x1
			y = y1
			z = z1
		end

		return f, g, h, setter
	end

	local f, g, h, setter = test()

	h()
	f()
	g()

	setter("x", "y", "z")

	h()
	f()
	g()
end

print(pcall(middleupvaluestest))


print('--------- nested upvalues ----------')
local function nestedupvaluestest()
	local f
	do
		local x = 10
		function g()
			print(x, f())
		end
	end

	function f()
		return 20
	end

	g()
end

print('nestedupvaluestest result:', pcall(nestedupvaluestest))

