I'm currently writing some kind of a "skeleton" for tests to be performed using Lauterbach scripts.
In this skeleton I want to have a part in which all test specific definitions shall be done, e.g. functions to set breaks on, variables to be altered etc. This part shall be just near the top of the script file, so that other users do not have to go through the complete script file, changing values here and there.
Some of the variables that'll be used are defined function-local within the C-code to be tested. So, these become available to the Lauterbach script only once the scope of that function has been entered - which is deeply within the skeleton script code.
Is there a way to define a macro for these variables just way before the scope has been entered?
Let's give some example structure:
LOCAL &funcToTest // the function we want to test
LOCAL &varToBeSet // a variable within the function we want to alter
LOCAL &valueToBeSet // the value we want to set &varToBeSet to
... // some more definitions here
&funcToTest=someFunc
&varToBeSet=status
&valueToBeSet=1
... // some test code following here that sets up log files, screen areas
... // start the program to be tested etc.
IF (Register(PC)==ADDRESS.OFFSET(&funcToTest))
(
// OK - we've hit the breakpoint inside the function to test
... // Run to some point where we can set the local variable
Var.Set &varToBeSet=&valueToBeSet
... // Go on with the program and see what happens - this will be logged
)
The problem is that Lauterbach complains at the line &varToBeSet=status
with Symbol not found in this context - which is correct, because it is a local variable.
Looking at the symbols via View->Symbols->SymbolsTreeView (or by giving the command Symbol.List.Tree) I can find the symbol (in this particular case found under the node some_module.some_function.status). Clicking on it gives the information in the TRACE32 status status line \\some_app\some_module\some_func\status with type (auto STATUS), scope local, location stack.
Changing my script to read &varToBeSet=\\some_app\some_module\some_func\status instead of &varToBeSet=status, however, does not help much. In this case Lauterbach complains with no access to that symbol.
Is there a way, I can delay evaluation of the macro to some point where it is actually used instead of having it evaluated when it is defined?
Use quotes:
&varToBeSet="\\some_app\some_module\some_func\status"
Related
It seems trivial, but I've searched far and wide.
I'm using this resource to make v8 run with ES Modules and I'm trying to implement my own search/load algorithm. Thus far, I've managed to make a simple system which loads a file from a known location, however I'd like to implement external modules. This means that the known location is actually unknown throughout the application. Take the following directory tree as an example:
~/
- index.js
import 'module1_index'; // This is successfully resolved to /libs/module1/module1_index.js
/libs/module1/
- module1_index.js
export * from './lib.js' // This import fails because it is looking for ./lib.js in ~/source
- lib.js
export /* literally anything */
The above example begins by executing the index.js file from ~. When module1_index.js is executed, lib.js is looked for from ~ and consequently fails. In order to address this, the files must be looked for relative to the file being executed at the moment, however I have not found a means to do this.
First Attempt
I'm given the opportunity to look for the file in the callResolve method (main.cpp:280):
v8::MaybeLocal<v8::Module> callResolve(v8::Local<v8::Context> context, v8::Local<v8::String> specifier, v8::Local<v8::Module> referrer)
or in loadModule (main.cpp:197)
v8::MaybeLocal<v8::Module> loadModule(char code[], char name[], v8::Local<v8::Context> cx)
however, as mentioned, I have found no function by which to extract the ScriptOrigin from the module. I should mention, when files are successfully resolved, the ScriptOrigin is initiated with the exact path to the file, and is reliable.
Second Attempt
I set up a stack, which keeps track of the current file being executed. Every import which is made is pushed onto the stack. Once the file has finished executing, it is popped. This also did not work, as there was no way to reliably determine once the file had finished executing.
It seems that the loadModule function does just that: loads. It does not execute, so I cannot pop after the module has loaded, as the imports are not fully resolved. The checkModule/execModule functions are only invoked on dynamic imports, making them useless to determining the completion of a static import.
I'm at a loss. I'm not familiar with v8 enough to know where to look, although I have dug through some NodeJS source code looking for an implementation, to no avail.
Any pointers are greatly appreciated.
Thanks.
Jake.
I don't know much about module resolution, but looking at V8's sources, I can see an example mapping a v8::Module to a std::string absolute_path, which sounds like what you're looking for. I'm not copying the whole code here, because the way it uses custom metadata is a bit involved; the short story is that it keeps a std::unordered_map to keep data about each module's source on the side. (I wonder if it would be possible to use Module::ScriptId() as that map's key, for simplification.)
Code search finds a bunch more example uses of InstantiateModule, mostly in tests. Tests often serve as useful examples/documentation :-)
I have one file "example.lua":
local function manipulate(something)
return string.rep(something, 3) -- repeats the given string
end
function apiFunction(somethingelse)
return manipulate(somethingelse)
end
and another files (main.lua) task is to "load"/"do" it:
loadAPI("example.lua", "externAPI") --< the part i need help with
externAPI.apiFunction("Test") --> should return TestTestTest
the thing that should happen is, that example.lua gets executed just like
dofile("example.lua")
but everything globally "defined" within example.lua (in this case the apiFunction) moves to the new generated global "externAPI" table and the rest (ie. manipulate) is hidden and only available from inside the example.lua file.
I've seen this bahaviour before in the minecraft mod "ComputerCraft" in which there is a function called "os.loadAPI("/somepath/sha-2") and it would define the definitions in the sha-2-chunk in the due to the name specified "sha-2"-table.
I've been searching for this sort of scoping/redirecting stuff for a while but there are no solutions putting the stuff into the new table.
I've been thinking of parsing the _G table after new indexes and move those to the new table but I'm sure there are some lua-magicians out here that know a much cleaner, better working solution to this.
All this is in one C lua_state* , so if there are any solutions adding this loadAPI function in C/C++ and just registrating it at the state this would be fine, too.
I've also looked at "require", but didn't seem to understand whether it does what I need.
Using Lua 5.2.3
Hope i didn't forget anything.
Thanks in advance :)
~InDieTasten
Try this:
function loadAPI(f,g)
_G[g]=setmetatable({},{__index=_G})
loadfile(f,"bt",_G[g])()
end
loadAPI("example.lua", "externAPI")
print(externAPI.apiFunction("Test"))
The following code works:
<cfoutput>#$.currentURL()#</cfoutput>
However, within a function, "$" is not available.
<cfscript>
function myTest() {
return $.currentURL();
}
</cfscript>
Does anyone know what actually is the equivalent of $ within a function?
Likewise, #pluginConfig.getDirectory()# works when used directly in cfoutput. However, within a cfscript function, it reports "unknown variable pluginConfig."
Thank you for advance for guiding me in the right direction.
When writing code outside the Mura Event Scope (like you do with that function), you have to obtain an instance of the Mura Scope ($) yourself. This can be done using the following code:
$ = application.serviceFactory.getBean('$');
Next you'll have to initialise the instance using an event object, a struct with value pairs or a 'siteID':
$.init(event);
$.init(myStruct);
$.init(siteID);
The same counts for the pluginConfig, this you can abtain via the Mura Scope. You'll have to pass the pluginID, moduleID, name or package of the plugin:
$.getPlugin(pluginID);
$.getPlugin(moduleID);
$.getPlugin(name);
$.getPlugin(package);
An other option you have is to pass the Mura Scope and the pluginConfig as arguments to the function. When writing a small plugin, this might be the easier way. But when writting medium or large plugins, it will get a bit messy when you're passing along these objects all the time.
The $ is used as a special framework variable in some CF frameworks (like Mura). You will need to figure out the framework context (if any) your code is executing in
I use Lua for my game engine logic. My main game loop is not done in Lua. Only special nodes in my scene hierarchy have Lua scripts attached. These scripts are executed every frame. The problem I face is that I need to keep global variable values from one frame to another.
My temporary solution looks like this:
finish = useBool("finish", false)
timer = useInt("timer", 0)
showTimer = useBool("showTimer", true)
startTimer = useInt("startTimer", 0)
play0 = useBool("play0", false)
play1 = useBool("play1", false)
play2 = useBool("play2", false)
play3 = useBool("play3", false)
delta = useInt("delta", 0)
gameOverTime = useInt("gameOverTime", 5000)
finishTime = useInt("finishTime", 5000)
checkPoint = useInt("checkPoint", 255)
<...> Game logic <...>
setInt("message", message);
setInt("checkPoint", checkPoint)
setInt("finishTime", finishTime)
setInt("gameOverTime", gameOverTime)
setInt("timer", timer)
setBool("play3", play3)
setBool("play2", play2)
setBool("play1", play1)
setBool("play0", play0)
setInt("startTimer", startTimer)
setBool("showTimer", showTimer)
setInt("timer", timer)
setBool("finish", finish);
I call special methods that retrieve global variables from hash maps in C++ at the beginning and I set them again at the end of the script.
Is there a way to do this implicitly?
Is it a bad design to use Lua not as the main game loop?
Well, while there is nothing technically wrong with your solution, you might start to notice some performance issues if you end up with a lot of global variables (something you should, in general, avoid).
With that said, there is room for improvement. For example:
At the beginning of the script, check if your global variable is nil. If it is, then you can initialize it, if not, this is probably not the first time you're running the script, so leave it unmodified. But that means a lot of pesky if-else statements, which one can easily forget about. We can do better!
I would recommend looking at Chapter 14: The Environment, from the Programming in Lua book. Here's a quick quote from the intro:
Lua keeps all its global variables in a regular table, called the environment. ... The other (actually the main) advantage is that we can manipulate this table as any other table. To facilitate such manipulations, Lua stores the environment itself in a global variable _G. (Yes, _G._G is equal to _G.)
Since _G is a table, it also has a metatable, so you can define __index and __newindex metamethods to handle access to and creation of global variables. You can find examples of this in section 14.2. Go read the whole chapter, it's not that long (if you're unfamiliar with metamethods and metatables, also look through chapter 13 - this is where Lua really shines in terms of flexibility).
Now that we've covered the trivial and normal methods, let's look at the overkill end of the spectrum. As an example I'll look at Unity's approach to scripting. A Unity javascript usually defines variables, functions, and types. Any variables defined outside of the scope of methods or types are persisted between frames because the script itself is not executed every frame. Instead, they let the script define functions and call the functions at the appropriate time. So if you want something executed every frame - you put it in the Update function. Every script can define it's own Update function because it has it's own scope. So every frame the scripting engine goes through all objects, checks if the script's scope has an Update method and calls it.
Back to Lua - a solution like this would involve creating separate environments for each object/script/whatever your node is. Then, instead of executing the script attached to your node every frame, your main loop will go through all the nodes and run a function inside of their environment. You can also switch environments, so you can set the global environment to your node's env before executing it, and then switch back when you're done. This allows your scripts to use globals as they see fit, have them persisted between frames and excludes the possibility of name collisions or global namespace pollution. Additionally you can use metamethods to nest the node's environment inside the actual global environment or inside an API environment with helper methods (basically, if __index does not find something it looks it up in a parent).
My current problem is that I have several enemies share the same A.I. script, and one other object that does something different. The function in the script is called AILogic. I want these enemies to move independently, but this is proving to be an issue. Here is what I've tried.
1) Calling dofile in the enemy's constructor, and then calling its script function in its Update function which happens in every game loop. The problem with this is that Lua just uses the script of the last enemy constructed, so all of the enemies are running the same script in the Update function. Thus, the object I described above that doesn't use the same script for it's A.I. is using the other enemies' script.
2) Calling dofile in the Update function, and then calling its script function immediately after. The problem with this is that dofile is called in every object's update function, so after the AILogic function runs and data for that script is updated, the whole thing just gets reset when dofile is called again for another enemy. My biggest question here is whether there is some way to retain the values in the script, even when I switch to running a different one.
I've read about function environments in Lua, but I'm not quite sure how to implement them correctly. Is this the right direction? Any advice is appreciated, thanks.
Edit: I've also considered creating a separate place to store that data rather than doing it in the Lua script.
Edit2: Added some sample code. (Just a test to get the functionality working).
-- Slime's Script
local count = 0;
function AILogic( Slime )
--Make the slime move in circles(err a square)
if count < 4 then
Slime:MoveDir( 0 );
elseif count < 8 then
Slime:MoveDir( 2 );
elseif count < 12 then
Slime:MoveDir( 1 );
elseif count < 16 then
Slime:MoveDir( 3 );
else
count = 0;
end
count = count + 1;
end
The lua interpreter runs each line as its own chunk which means that locals have line scope, so the example code can't be run as-is. It either needs to be run all at once (no line breaks), without locals, or run in a do ... end block.
As to the question in the OP. If you want to share the exact same function (that is the same function at runtime) then the function needs to take the data as arguments. If, however, you are ok with using the same code but different (runtime) functions than you can use closures to hold the local/individual data.
local function make_counter()
local count = 0
return function ()
local c = count
count = count + 1
return c
end
end
c1 = make_counter()
c2 = make_counter()
c3 = make_counter()
print(c1())
print(c1())
print(c1())
print(c1())
print(c2())
print(c3())
print(c2())
print(c3())
print(c2())
print(c3())
Alternatively, you could play with the environment of the function each time it is called, but that will only work correctly for some cases (depends on what the internals of the function are).
The canonical reference for this is link text. Explaining this briefly we'll work off the following code from the site:
a = 1
local newgt = {} -- create new environment
setmetatable(newgt, {__index = _G})
setfenv(1, newgt) -- set it
The first line sets up the (global) variable "a". You can view this as setting default values for your code. (Keep in mind that in Lua all variables are global unless you declare them with "local".)
The next line creates a table that will be your new environment. It is local to the function/chunk you're executing in so it won't be trashed by anything else that runs now or later.
The third line is the beginnings of the magic. To understand it you're going to have to understand metamethods In essence, however, you're using Lua's metamagic to ensure that any global names that aren't defined in your soon-to-be function environment get resolved in the context of your old global environment. Basically it means if you use a name that's not in your function environment, Lua will automagically hunt in the global environment you used to have to find the name. (In a word: inheritance.)
The fourth line is where you get what you're looking for. Setfenv(1,...) means that this changes the environment for your current function. (You could use 2 for the calling function, 3 for the calling function's caller, etc. on up the line.) The second parameter is the table you just set up, complete with inheritance of the old behaviour. Your function is now executing in a new global environment. It has all the names and values of the old environment handy (including functions and that global variable "a" you put in). If, however, you WRITE to a name it will not overwrite the global state. It will overwrite your local copy of it.
Consider the following subsequent code:
a = 10
b = 20
What you have done now is made your function environment table look like this:
{a = 10, b=20}
Your "global" environment, in short, contains two variables only: a (value 10) and b (value 20). When you access "a" later you'll get your local copy with 10 -- the old global value stored in your metatable is shadowed now and is still set to 1 -- and if you access "b" you'll get 20, despite the original global state likely not even having a variable "b" to access. And you'll still be able to access all the functions, etc. you've defined before this point as well.
Edited to add test code to debug OP's problem.
I put the following code into "junk.lua":
a = 1
local newgt = {}
setmetatable(newgt, {__index = _G})
setfenv(1, newgt)
print(a)
a = 10
print(a)
print(newgt)
The output of it is as follows:
$ lua junk.lua
1
10
table: 0x976d040
This is using Lua 5.1.4. What is the output you're seeing?