This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
grabie2's profile picture

[1.48] Few bugs with environment

Started by grabie2, 28 December 2012 - 10:43 AM
grabie2 #1
Posted 28 December 2012 - 11:43 AM
In attachment minimalized version of my multitasking OS
to boot it, you have to place it in computer root directory(or change path in boot file)


I found few bugs with environment:
1st: When you boot my OS(run boot), after few seconds everything runs and you can see error "task 'tty1' has errored": ttyManager:37: attempt to call nil" line 37 of bin/ttyManager is:

local function TTY(n, _f, PID) --line 31
  local fnFile, err = loadfile( fs.combine(os.getPath(), "/bin/lua" ))
  if fnFile then
	-- _G = getfenv()  ------------BUG, also workaround another bug
	term._write("test not global")
getfenv().term._write("test getfenv") ------BUG getfenv isn't equal to _G
	_G["term"]._write("test global") -----------BUG getfenv isn't equal to _G
	local _api = _G
	local tEnv = {}
	setmetatable( tEnv, { __index = _api } )
	setfenv( fnFile, tEnv )
  end
  login(os.version().."\n TTY "..tostring(n), fnFile, PID)
end --line 44
I don't know how it happen to happen, as far as I know in lua it is impossible that getfenv() isn't equal to _G variable
2nd bug is workaround the 1st bug:

_G = getfenv()
According to lua documentation: http://www.lua.org/m...ual.html#pdf-_g
Lua itself does not use this variable [_G] ; changing its [_G] value does not affect any environment
So, this workaround shouldn't work.
And to avoid some interpretations, _G isn't global for every function in lua 5.2 there is _ENV which is only one and global environment. If _G would be global, then it would mess up all multitasking code in bin/netOS

But please first fix 1st bug and then 2nd ;)/>

[attachment=827:netOS.zip]
AfterLifeLochie #2
Posted 28 December 2012 - 11:55 AM
I think you're a touch missing the target with regards to getfenv().

getfenv() works in two ways - returning the environment of a function, or, returning the environment at a stack (or the global). For example, if I have a function inside a function, and I called getfenv(<that-function-in-the-function>), I'd be given all the variables inside the outside function. (This is a really awkward example). getfenv() also allows getting the environment at a particular stack depth. Calling getfenv(1) returns the *local* environment (for example, if you were inside a function, and you'd previously called setfenv(<that function>)), and calling getfenv(0) returns the value of _G.

If you do not specify any value for getfenv(), it returns the local context - which I have a feeling you're not looking for, but rather, the _G global table. Try with getfenv(0), and that should return _G.

As far as the "attempt to call nil" error, this is why - you've thrown in an underscore.
 _G["term"]._write("test global")
should be
 _G["term"].write("test global")
(From the global, get the term table, and then call "write" from that table.)
grabie2 #3
Posted 28 December 2012 - 12:04 PM
underscore is on purpose,because termAPI is modified by OS(in this case ttyManager), and function term._write is equivalent original term.write() and term.write() is equivalent to write itself, you'd know that it you'd read bin/ttyManager ;)/>

getenv() without parameters return what was set by setfenv and should be equal to _G

Although thanks for reply!

I just found that most updated CC-emu by tomass1996 doesn't have first bug.
AfterLifeLochie #4
Posted 28 December 2012 - 12:17 PM
underscore is on purpose,because termAPI is modified by OS(in this case ttyManager), and function term._write is equivalent original term.write() and term.write() is equivalent to write itself, you'd know that it you'd read bin/ttyManager ;)/>

getenv() without parameters return what was set by setfenv and should be equal to _G

Although thanks for reply!

I just found that most updated CC-emu by tomass1996 doesn't have first bug.
It's not a bug - it's the correct behaviour of Lua. If you've previously setfenv() somewhere up the function chain, you can't break out of that environment unless you explicitly specify the context. Take the following:


function a()
	print("Function a, in the custom context.")
	b()
end

function b()
   print("I'm in the same context as function a was.")
   local _G = _G
   -- the local _G and the _G are for *this* function, which only has print.

   local myEnv = getfenv()
   -- myEnv = the _G for *this* function, which *still* only has print.

   local globalEnv = getfenv(0)
   -- globalEnv = the really real _G.
end

setfenv(a, { print = _G.print })
grabie2 #5
Posted 28 December 2012 - 12:24 PM
yea, but what i'm trying to say is that _G isn't the LOCAL environment as it should be. It's actually as far as I see the one set by CC, but in CC-Emu it's working OK - _G is LOCAL environment.

EDIT:
BTW. if you create coroutine is it actually creating a thread(which has it's own GLOBAL environment)?