I know that webassembly is a stack-based virtual machine (or that it is bytecode run on such a machine). This means that instructions like (i32.const) or (i32.load) push values onto the stack and instructions like (i32.add) or will pop values from the stack to use. However, does that mean that local variables made with:
(local $var i32)
inside of a function automatically reserve space in the stack? Or is that only true for "executable" instructions? Wouldn't it be possible to pop the stack local variable that way? Also how would the amount of the stack to pop be determined when returning from a function call?
I realize that local variables have their own instructions like (local.set) and (local.get), so it feels like they live on a different stack than the one where temporary data from executable instructions live.
How one will implement the WebAssembly runtime is not strictly defined by the specification. What is defined is the outcome of the execution.
Some instructions can trap in certain cases. These cases are defined by the specification. For a module to be valid, the local get/set instructions indexes (or names) must be valid in their current scopes. That means that during runtime these instructions must not trap because the indexes/names they reference are invalid.
That means that the runtime environment must allocate the needed stack space for all locals during the call of the function. The implementation may have limitations on the frames/values in the stack. There are discussions about the maximum evaluation stack depth. From the specs:
If the runtime limits of an implementation are exceeded during execution of a computation, then it may terminate that computation and report an embedder-specific error to the invoking code.
Additionally to that the stack in WebAssembly is polymorphic and at runtime a valid program must not be able to pop more then it has pushed. However, during validation it is possible, cite:
However, a polymorphic stack cannot underflow, but instead generates Unknown types as needed.
Related
I'm reading some source codes of a project, which is a combination of c++ and lua, they are interwined through luabind.
There is a la.lua file, in which there is a function exec(arg). The lua file also uses functions/variables from other lua file, so it has statements as below in the beginning
module(..., package.seeall);
print("Loading "..debug.getinfo(1).source.."...")
require "client_config"
now I want to run la.exec() from interactive terminal(on linux), but I get errors like
attempt to index global 'lg' (a nil value)
if I want to import la.lua, I get
require "la"
Loading #./la.lua...
./la.lua:68: attempt to index global 'ld' (a nil value)
stack traceback:
./lg.lua:68: in main chunk
[C]: in function 'require'
stdin:1: in main chunk
[C]: ?
what can I do?
Well, what could be going wrong?
(Really general guesswork following, there's not much information in what you provided…)
One option is that you're missing dependencies because the files don't properly require all the things they depend on. (If A depends on & requires B and then C, and C depends on B but doesn't require it because it's implicitly loaded by A, directly loading C will fail.) So if you throw some hours at tracking down & fixing dependencies, things might suddenly work.
(However, depending on how the modules are written this may be impossible without a lot of restructuring. As an example, unless you set package.loaded["foo"] to foo's module table in foo before loading submdules, those submodules cannot require"foo". (Luckily, module does that, in newer code without module that's often forgotten – and then you'll get an endless loop (until the stack overflows) of foo loading other modules which load foo which loads other modules which …) Further, while "fixing" things so they load in the interpreter you might accidentally break the load order used by the program/library under normal operation which you won't notice until you try to run that one normally again. So it may simply cost too much time to fix dependencies. You might still be able to track down enough to construct a long lua -lfoo-lbar… one-off dependency list which might get things to run, but don't depend on it.)
Another option is that there are missing parts provided by C(++) modules. If these are written in the style of a Lua library (i.e. they have luaopen_FOO), they might load in the interpreter. (IIRC that's unlikely for C++ because it expects the main program to be C++-aware but lua is (usually? always?) plain C.) It's also possible that these modules don't work that way and need to be loaded in some other way. Yet another possibility might be that the main program pre-defines things in the Lua state(s) that it creates, which means that there is no module that you could load to get those things.
While there are some more variations on the above, these should be all of the general categories. If you suspect that your problem is the first one (merely missing dependency information), maybe throw some more time at this as you have a pretty good chance of getting it to work. If you suspect it's one of the latter two, there's a very high chance that you won't get it to work (at least not directly).
You might be able to side-step that problem by patching the program to open up a REPL and then do whatever it is you want to do from there. (The simplest way to do that is to call debug.debug(). It's really limited (no multiline, no implicit return, crappy error information), but if you need/want something better, something that behaves very much like the normal Lua REPL can be written in ~30 lines or so of Lua.)
My delphi application runs scripts using JvInterpreter (from the Jedi project).
A feature I use is runtime evaluation of expressions.
Script Example:
[...]
ShowMessage(X_SomeName);
[...]
JvInterpreter doesn't know X_SomeName.
When X_SomeName's value is required the scripter calls its OnGetValue-callback.
This points to a function I handle. There I lookup X_SomeName's value and return it.
Then JvInterpreter calls ShowMessage with the value I provided.
Now I consider switching to DelphiWebScript since it has a proper debug-interface and should also be faster than JvInterpreter.
Problem: I didn't find any obvious way to implement what JvInterpreter does with its OnGetValue/OnSetValue functions, though.
X_SomeName should be considered (and actually is, most of the time) a variable which is handled by the host application.
Any Ideas?
Thanks!
You can do that through the language extension mechanism, which has a FindUnknownName method that allows to register symbols on the spot.
It is used in the asm lib module demo, and you can also check the new "AutoExternalValues" test case in ULanguageExtensionTests, which should be closer to what you're after.
I'm implementing Lua scripting engine in my c++ game engine and I was wondering what is the best way to store and execute Lua scripts. I have many scene nodes where each of them could have it's own script assigned. Is calling lauL_dofile(...) every frame for that specific script a viable option, or is there a better way? For example, is there a way to store already parsed scripts? I was looking at luaL_loadfile and lua_pcall. I thought I would load scripts with first one, and call them with second one when I need, but lua_pcall doesn't seem to have an unique id as a parameter, so how should I know which script to execute?
If you're going to use the Lua API, you need to become comfortable with the Lua stack. And one of the most important things you can learn to do is understanding how to read the Lua API docs. For every function, there is a notation on the right about exactly how it affects the stack (if it modifies the stack at all).
luaL_loadfile loads a file and pushes that file as a Lua function onto the stack. lua_pcall executes a function on the stack. But it has a number of caveats about how it does stuff.
The way calling functions through Lua works in terms of the stack is simple. You push the function you want to call. Then you push all of the arguments, in order, from first to last. Then you issue your call of that function. lua_pcall works in this way. This means that the location of the function to execute is always nargs + 1, relative to the top of the stack, where nargs is the number of arguments you're passing to the function.
Note that lua_pcall will pop the function from the stack (along with all of the arguments). If you just loaded the file, this will be the only reference to that function in Lua. Thus, you will not be able to execute the file again. You should duplicate the function before pushing its arguments onto the stack, using lua_pushvalue to copy it. You should probably stick it in the LUA_REGISTRYINDEX table or something, so that it's value is preserved.
As I commented, you usually call luaL_loadfile at initialization time. The loaded files usually define some [global] names (or fill some slots in some global table) as Lua functions. The lua 5.2 documentation gives an example (§4 lua_call) of how to call one of them. You'll do such calls (perhaps using lua_pcall or lua_call) at appropriate places of your application, by pushing appropriate things on the Lua stack.
I write a C program gets in an environment variable's name and print out it's memory address, simply use the getenv() function to do the job. Let's say I wanna have the address location of PATH --> ./test PATH. But when I debug that program in gdb, the memory location of that variable is different. Can you explain in detail why is there such a different?
To be more exact:
./test PATH --> 0xbffffd96
debug in gdb --> 0xbffffd53
[edit] Thanks for your explanations. What I actually in question about is, how the memory address of a variable (in this case, an environment variable) changes with different programs. For example, I have 2 program a.out and b.out
./a.out --> PATH's address is some number
./b.out --> another number
So, what causes this difference between 2 numbers? I hope I have clearly demonstrated what I want to ask. Thanks mates.
Typically, environment variables are part of some "process data block", and those are inherited from the starting process. If you are running a program in a debugger, that debugger will have its own process data block and your program will inherit its process data block from the debugger. That in turn might have inherited the program data block of the IDE.
This doesn't matter anyway, because the interface to the environment variables doesn't give you that kind of details. For instance, on Windows it's quite likely that the environment variables will be converted from Unicode to your local 8 bit codepage when you ask for them. You'd never see the original variable, just (an approximation of) its value.
Perhaps you want to do?
printf("%s",getenv("PATH"));
Getting the environment variable string does make sense.
But, the address where the system gives you the string, has no relevance anywhere
(particularly outside the scope of this program).
You should be interested in the environment string value rather than its address.
If you have any reason to use the address, please give that here.
For example,
echo $PATH
gives me,
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin: ... etc
All my programmatic interest with PATH would be in its contents not any sort of address.
Why would you expect it to return the same memory location every time? getenv returns "a pointer to a string containing the value for the specified name." It is not specified which memory location the string is located at, nor whether that location will later be overwritten.
I'm lead dev for Bitfighter, and we're using Lua as a scripting language to allow players to program their own custom robot ships.
In Lua, you need not declare variables, and all variables default to global scope, unless declared otherwise. This leads to some problems. Take the following snippet, for example:
loc = bot:getLoc()
items = bot:findItems(ShipType) -- Find a Ship
minDist = 999999
found = false
for indx, item in ipairs(items) do
local d = loc:distSquared(item:getLoc())
if(d < minDist) then
closestItem = item
minDist = d
end
end
if(closestItem != nil) then
firingAngle = getFiringSolution(closestItem)
end
In this snippet, if findItems() returns no candidates, then closestItem will still refer to whatever ship it found the last time around, and in the intervening time, that ship could have been killed. If the ship is killed, it no longer exists, and getFiringSolution() will fail.
Did you spot the problem? Well, neither will my users. It's subtle, but with dramatic effect.
One solution would be to require that all variables be declared, and for all variables to default to local scope. While that change would not make it impossible for programmers to refer to objects that no longer exist, it would make it more difficult to do so inadvertently.
Is there any way to tell Lua to default all vars to local scope, and/or to require that they be declared? I know some other languages (e.g. Perl) have this option available.
Thanks!
Lots of good answers here, thanks!
I've decided to go with a slightly modified version of the Lua 'strict' module. This seems to get me where I want to go, and I'll hack it a little to improve the messages and make them more appropriate for my particular context.
There is no option to set this behavior, but there is a module 'strict' provided with the standard installation, which does exactly that (by modifying the meta-tables).
Usage:
require 'strict'
For more in-depth info and other solutions: http://lua-users.org/wiki/DetectingUndefinedVariables, but I recommend 'strict'.
Sorta.
In Lua, globals notionally live in the globals table _G (the reality is a bit more complex, but from the Lua side there's no way to tell AFAIK). As with all other Lua tables, it's possible to attach a __newindex metatable to _G that controls how variables are added to it. Let this __newindex handler do whatever you want to do when someone creates a global: throw an error, permit it but print a warning, etc.
To meddle with _G, it's simplest and cleanest to use setfenv. See the documentation.
"Local by default is wrong". Please see
http://lua-users.org/wiki/LocalByDefault
http://lua-users.org/wiki/LuaScopingDiscussion
You need to use some kind of global environment protection. There are some static tools to do that (not too mature), but the most common solution is to use runtime protection, based on __index and __newindex in _G's metatable.
Shameles plug: this page may also be useful:
http://code.google.com/p/lua-alchemy/wiki/LuaGlobalEnvironmentProtection
Note that while it discusses Lua embedded into swf, the described technique (see sources) do work for generic Lua. We use something along these lines in our production code at work.
Actually, the extra global variable with the stale reference to the ship will be sufficient to keep the GC from discarding the object. So it could be detected at run time by noticing that the ship is now "dead" and refusing to do anything with it. It still isn't the right ship, but at least you don't crash.
One thing you can do is to keep user scripts in a sandbox, probably a sandbox per script. With the right manipulation of either the sandbox's environment table or its metatable, you can arrange to discard all or most global variables from the sandbox before (or just after) calling the user's code.
Cleaning up the sandbox after calls would have the advantage of discarding extra references to things that shouldn't hang around. This could be done by keeping a whitelist of fields that are allowed to remain in the environment, and deleting all the rest.
For example, the following implements a sandboxed call to a user-supplied function with an environment containing only white-listed names behind a fresh scratch table supplied for each call.
-- table of globals that will available to user scripts
local user_G = {
print=_G.print,
math=_G.math,
-- ...
}
-- metatable for user sandbox
local env_mt = { __index=user_G }
-- call the function in a sandbox with an environment in which new global
-- variables can be created and modified but they will be discarded when the
-- user code completes.
function doUserCode(user_code, ...)
local env = setmetatable({}, env_mt) -- create a fresh user environment with RO globals
setfenv(user_code, env) -- hang it on the user code
local results = {pcall(user_code, ...)}
setfenv(user_code,{})
return unpack(results)
end
This could be extended to make the global table read-only by pushing it back behind one more metatable access if you wanted.
Note that a complete sandbox solution would also consider what to do about user code that accidentally (or maliciously) executes an infinite (or merely very long) loop or other operation. General solutions for this are an occasional topic of discussion on the Lua list, but good solutions are difficult.