I read in another post that I couldn't get actual value for variables with unnamed identifiers. I need to get the variables with named identifier in instruction I with its actual value for example: 'int x =0;' I need to get that variable v has value 0. When I used ' I->getOperand(0)' I got that instruction itself or alloca instruction for some operations like sext.
To read the variable name, have look inside lli. You would need to look inside the ExecutionContext, and how the interpreter is executed. Essentially the interpreter visits instructions as they are executed. Inside the visit functions, you can read the name of the variables.
Related
General CS question because I was surprised by behavior of let in Netlogo.
If I declare a variable from within an if statement per below, is it common for the scope of that variable to be limited to that if statement?
I thought scope generally referred to functions rather than constructs like a loop or if statement. How common is that?
if x > y :
int i = 2
else:
int i = 3
print(i)
would return: "error: (i) does not exist"
I´m not sure, if this answers your question, but the Netlogo Programming Guide on local variables, created with let, states:
Local variables
A local variable is defined and used only in the context of a
particular procedure or part of a procedure. To create a local
variable, use the let command. If you use let at the top of a
procedure, the variable will exist throughout the procedure. If you
use it inside a set of square brackets, for example inside an “ask”,
then it will exist only inside those brackets.
to swap-colors [turtle1 turtle2]
let temp [color] of turtle1
ask turtle1 [ set color [color] of turtle2 ]
ask turtle2 [ set color temp ]
end
The same is true if a local variables is created within an if or ifelse statement. Therefore if you want to use the variable later on, than declare it before and outside the ifelse statement with let. Than assign the value with set within the ifelse statement.
I'd like to be able to write some Lua code like this:
y=x+1
and be able to get the names of all variables (x and y in this case) so that I can read from/write to them in the calling C++ program. The problem is that x is uninitialized, so this chunk will not execute and therefore neither variable will appear in the globals table. My current work-around is to have the user explicitly declare that they want to initialize x externally (as well as how to initialize it), then I pre-pend the Lua script with an appropriate declaration for x, so that the final script looks like this:
x= /*some value calculated outside of the Lua script*/
y=x+1
Although this works, I'd really like to have a way to automatically list all uninitialized variables in the Lua code and present them to the user, instead of the user having to remember to explicitly declare them. A function that parses the Lua code without executing it would probably be what I want. I've tried the function luaL_loadstring, but x and y don't show up in the globals table.
Since this is a bit vague, I'll give an actual use case. My C++ code basically performs optimizations on functions, such as finding a root or a maximum. I want the user to be able to define custom functions (in the form of Lua scripts), which in general will have one or more inputs and one or more outputs. The user will define which parameters the optimizer should operate on. For example, the user may want to find the minimum of y=x^2. The way I'd like it to work is that the user writes a Lua script consisting of nothing more than y=x^2, and then tells the optimizer to vary x in order to minimize y. On each iteration of the optimizer, the current guess for x would be automatically pasted into the user script, which is then executed, and then the value of y is pulled from the Lua state to be fed back to the optimizer. This is how I have it working now, however it's a bit clumsy from a UX perspective because the user has to manually declare that x is a Lua variable. This gets tedious when there are many variables that require manual declaration. It would be much better if I could automatically scan the script and show the user a list of their undeclared variables so they could then use drag-and-drop and other GUI sugar to do the manual declaration.
Lua isn't meant to work like that. Lua/C interop is intended to be collaborative; it's not supposed to be that C can do whatever it wants.
Using your example, if you have a Lua script that is supposed to take a value from C and return that value + 1, then you spell that in Lua like this:
local x = ... --Get the first parameter to the chunk.
return x + 1 --Adds 1 to the value and returns it.
You compile this string into a Lua chunk and call it like a Lua function. You pass it the value you want to manipulate and get the return value from the Lua stack.
The idea is not that C code can just reach into a Lua script and shove data into it arbitrarily. The above chunk takes parameters from the user and provides return values to the user. That's typically how C interfaces with Lua.
Yes, you can write values to globals and have the Lua script read them, and write its "results" to globals that the external code reads. But this is not the most effective way to interact with scripts.
I'd really like to have a way to automatically list all uninitialized variables
There's no such thing in Lua as an "uninitialized variable". Not in the way that you mean.
Yes, there are globals. But whether that global has a value or not is not something the Lua script can control. A global is global after all; you can set a global variable from outside of the script (for example, see lua_setglobal). If you do, then a script that reads from it will read the value you set. But it doesn't know anything about that.
What you want is a static code analyzer/Lua linter. Take a look at Luacheck:
Luacheck is a static analyzer and a linter for Lua. Luacheck detects
various issues such as usage of undefined global variables, unused
variables, and values, accessing uninitialized variables, unreachable
code and more. Most aspects of checking are configurable: there are
options for defining custom project-related globals, for selecting set
of standard globals (version of Lua standard library), for filtering
warnings by type and name of related variables, etc. The options can
be used on the command line, put into a config or directly into
checked files as Lua comments.
There is also Lualint, and similar Lua linters for Atom, VSCode, or your fav IDE.
class Controller
def index
puts "hello"
end
end
macro handler(controller, action)
c = {{controller}}.new
c.{{action.id}}
end
# this doesn't work
temp = :index
handler Controller, temp
# this works
handler Controller, :index
Somehow on the first case, the macro gets expanded to c.temp instead of c.index
Is it possible to call a function inside a class like in above code snippet.
Edit:
I am trying to achieve something like this, https://github.com/Amber-Crystal/amber/blob/master/src/amber/dsl/router.cr#L16
temp is a runtime variable, while macros are interpreted at compile time. That means the Crystal compiler can't actually know the value of temp, as it is only known at runtime. Tracing variables to literal values could be done to some degree, but would be expensive and brittle to use, since a small change may make it impossible.
When you call a macro, the arguments are actual AST nodes, expressions of parsed source code. So in your example the macro gets a TypeNode as first argument and a Var as second argument.
I am writing a plugin for Stata in C++, and it seems to me that accessing the data depends on the order of variables passed to the plugin, as SF_vdata() only takes integer arguments to index the variables.
The best solution I have at the moment, is to first run ds, store the macro containing all variable names, and then call my plugin. My plugin can then search the macro for the variable that it is interested in, and get the index base don its position in the list.
This works, but I would like my plugin not to depend on certain Stata commands being run first. I know this is silly, as the plugin requires the dataset to be formatted in a specific way, but something feels wrong about first having to call ds and store a macro before calling my plugin.
Is there anyway to access the order of variable names from inside the plugin if ds is not called first?
I agree with Nick. Unfortunately your macro solution is the only answer, and is what I use. You can only access the data directly using the SF_data functions, as a "matrix", and that's all you get by default, there are no headers like in a table. I use macros to save all the data information and pass the whole dataset, reading the variable I'm interested in, just like you, and even wrote translators to retain the format settings, but have not yet used the value labels.
The scope evaluation order is well known/documented when using variables. However I can't find any information about the scope evaluation order when setting a variable.
One would presume it's the same list, but there appears to be a few caveats as demonstrated here:
<cfset qryChain = queryNew("id,next")>
<!--- add some data so the cfloop kicks in --->
<cfloop query="qryChain">
<cfset Next = StructNew()>
<cfset Next.id = qryChain.next>
</cfloop>
The above code is trying to reuse a variable name that it shouldn't, but fails in an unexpected way.
Since the cfsets are inside a query loop, item 4 of the scope evaluation order should be used for both. Instead Next is being evaluated as Variables.Next (item 6), and then Next.id is being evaluated as Variables.qryChain.next.id (item 4) and fails.
Is this documented anywhere? Is it simply items 1-6 of the "using" list above with a few caveats? Are these caveats intentional, or bugs? What other caveats are there?
I think I understand what is going on here. The behavior you are seeing is from scope searching when accessing variables in order to set them. When you set a variable without scoping it, ColdFusion will search the scopes to see if that variable exists anywhere first, and if it does, it will set it there.
In your first example:
<cfset qryChain = queryNew("id,next")>
<!--- add some data so the cfloop kicks in --->
<cfloop query="qryChain">
<cfset Next = StructNew()>
<cfset Next.id = qryChain.next>
</cfloop>
When you are creating your "Next" variable it is actually placing that variable into the VARIABLES scope, you can prove that if you dump the variables scope at any time during the looping process. You will see a "Next variable" with an empty struct.
The problem is in the next line. When you try to ACCESS the Next variable to set a new key into it, ColdFusion is finding the Next variable that exists in the Query result first, because while looping a query the Query scope (not really a scope, but it works like one in this case) has a higher precedence than the Variables scope. That variable does not contain a struct, so you will get an error about how you are referencing it.
Scope searching is happening, but it is not really while setting, it is while accessing in order to set.
Here is a working example to demonstrate this.
<cfset qryChain = queryNew("id,next")>
<cfset queryAddRow(qryChain, 3) />
<cfdump var="#qryChain#">
<!--- add some data so the cfloop kicks in --->
<cfloop query="qryChain">
<cfset Next = StructNew()>
<cfdump var="#variables#">
<cfset Next.id = qryChain.next>
<cfdump var="#qryChain#">
</cfloop>
in this example, I show that after you create the next variable it does exist in the variables scope, but when you immediately try to set a key into it without scoping that access you will instead get the NEXT variable from the current record in the query. This is only happening because the query happens to have record with a column name that happens to match the variable you are trying to use.
So why doesn't ColdFusion try to set the StructNew() into the Query scope (pseudo-scope)? The query cannot be manipulated using dot notation. Again, it is not really a scope. So in this sense it is read-only and is being skipped over
To manipulate a query resultset in CF you must use query functionsVARIABLES scope. Because unscoped variables are always placed in the VARIABLES scope. In the line where you try to set the id however, there is another phase going on in the background where it needs to access the variable in a read capacity first, and then try to perform the set. In this case, it DOES find the NEXT variable in the query because scope searching will occur first to determine in NEXT exists to set that key into and then when you try to set something to it, it fails.
As for your second set of examples, this is expected behavior and is easily explained.
In the first example, you are varing your variable (which places it in the local scope). You are then setting the value of that variable. When you set a value to a variable (without scoping it) ColdFusion checks to see if that variable already exists anywhere (so it does a scope search, again this is accessing at this point, not setting) it will find it in the local scope and then set the value there. After that you set the value again, this time properly scoping it, so no searching is done.
In the second example, you are not varing the variable when it is initially set, it does not exist anywhere, and so it is set to the variables scope. If it had already existed in the local scope, then ColdFusion would have found it and set it there (as in your first example), but since it did not exist, and it was not var'd it was set to the variables scope.
Finally, in your last example, you explicitly scope your variable and so it will be set in the local scope. You then set it again without scoping it. ColdFusion will find it in the local scope and overwrite it.
The moral of the story is, scope your variables. I tis important to get expected behavior. Scope-searching was never a good idea, but unfortunately, it is here to stay. I don't see anything here that I would call a bug, or even unpredictable behavior if you understand the way scope searching works.
Scope evaluation during assigment
I am aware of two different methods of scope evaluation when creating variables in ColdFusion. I haven't tested every possible instance, but this is how it should work.
The first instance uses the full list of scopes in evaluating unscoped variables. This is used by cfparam when creating variables. If ColdFusion does not find a variable with the given name then it will create it in the Variables scope.
The second instance uses the first 6 scopes in evaluating unscoped variables and then if unsuccessful will also create the variable in the Variables scope. This is employed by cfset and any other tags that creates variables, such as cfhttp with the result attribute, and cfsavecontents variable attribute.
As you observed there is the odd "sometimes ignore" the query scope issue. I would classify that as a bug, but someone may yet be able to provide a reason why the exception needs to be made.
Hoisting
Although ColdFusion was designed to copy JavaScript in a lot of ways (specifically cfscript) there is a subtle deviation which I haven't seen documented. With regard to functions (both script and tag), JavaScript employs hoisting, whereas ColdFusion does not.
Hoisting is the process of automatically moving the declaration of a variable to the top of the function, while maintaining the code placement of the assignment of the variable. The means that the scope of a variable will not change in JavaScript, but it can in ColdFusion.
Prior to CF9 the var keyword had to be used at the top of the function, essentially negating the need for hoisting. This is different from JavaScript, where var can be used anywhere in a function and employs hoisting. With CF9 ColdFusion adopted the declare anywhere philosophy, but neglected to implement hoisting.
In both the following examples JavaScript would only be dealing with a single scope, with x being function local.
<!--- sets variables in 1 scope --->
<cfscript>
var x = 0;
x = 1;
local.x = 7;
</cfscript>
Compared to:
<!--- sets variables in 2 scopes --->
<cfscript>
x = 1;
var x = 0;
local.x = 7;
</cfscript>
To avoid the potential pitfalls created by the lack of hoisting you can either var only at the top of the function, or do things as many have prior to CF9 and declare a var structure at the top of the function and prefix all variables with that (remembering to not name it local). e.g.
<cfset var localVars = StructNew()>
<cfset localVars.x = 7>
<cfset localVars.y = 1>
var vs local
In functions var appears to be a second class citizen to the local scope. If you try to set a local variable to the same name as an argument using var you will receive an error message saying Use local to define a local variable with same name. despite var and local supposedly being equivalent.
More
There may be additional caveats and bugs, however I'm not aware of there being any documented cases.
You're getting this error, presumably (since it's the error I received):
You have attempted to dereference a scalar variable of type class coldfusion.sql.QueryColumn as a structure with members.
This is because when you are within a cfloop for a query, the query scope takes precedence over the variables scope when evaluating a scope-less variable. However, when you are assigning scope-less variables (either within a cfloop query context or not) then you use the variables scope. So when you assign
<cfset Next = StructNew()>
You are setting the "Next" variable to the variables. scope. However, when you attempt to evaluate Next (by referring to its key, .id), like so:
<cfset Next.id = qryChain.next>
Now you are getting Next from the query scope (and since Next in the query scope is not a structure, you get an error).
So, to try to answer your main question - when you are assigning a variable with no scope specified, CF will put the variable in the variables scope. When you attempt to evaluate a variable with no scope specified, then it will use the normal scope-precedence rules to find a match (in this case, finding one in the query scope).