I am iterating over the Module's function lists as shown below.
I am seeking for a way to find out if a Function *f is a declaration or a definition. (By dumping the function it seems that the list contains the two types.)
for (Module::iterator f = M->begin(), fend = M->end(); f != fend; ++f) {
...
}
From the Function manual:
If the BasicBlock list is empty, this indicates that the Function is actually a function declaration: the actual body of the function hasn’t been linked in yet.
and in the next section on Important Public Members of the Function, you'll find the function you want:
bool isDeclaration()
Return whether or not the Function has a body defined. If the function is “external”, it does not have a body, and thus must be resolved by linking with a function defined in a different translation unit.
which does the emptiness check for you.
Related
I would like to understand how can I analyze methods / functions body to find types that are explicitly referenced from it. I have success analyzing method declaration (return type, parameter types, etc..), however I have no idea how to do that for body.
Assuming following function:
String someFunction(int param) {
final list = <String>['a', 'b', 'c']; // -> DartTypes: String, List<String>
final myClass = MyClass<Arg>(); // -> DartTypes: Arg, MyClass<Arg>
final functionCall = anotherFunction<FunctionArg<Arg>>(); // -> DartTypes: Arg, FunctionArg<Arg>
return 'result';
}
// At is point I would like to know that my function depends on
// String, List<String>, Arg, MyClass<Arg>, FunctionArg<Arg>
// in term of DartType instances with proper typeArguments.
I tried getting AstNode for method element described here: https://stackoverflow.com/a/57043177/2033394
However I could not get elements from nodes to figure out their types. Their declaredElement values are always null. So I can not get back to Element API from AST API.
If you've used the exact snippet from the answer you've referenced, the problem is likely in getParsedLibraryByElement(). This method only parses the referenced library - meaning that you'll get an AST that doesn't necessarily have semantic references (like the declaredElement of AST nodes) set.
Instead, you'll want to use getResolvedLibraryByElement. The AST returned by that method will have its types and references fully resolved.
With the resolved AST, you could visit the body of the method with a custom visitor to find type references. Your definition of "referenced types" isn't really exact - but perhaps you can collect types in visitNamedType for type references and visitVariableDeclaration to collect the types of variables.
I am wondering about a particular statement in the Moloch v2.1 smart contract code:
https://github.com/Moloch-Mystics/Molochv2.1/blob/main/Flat_Moloch_v2.1.sol
In the Moloch contract, there is a contract level mapping called members
mapping(address => Member) public members;
As expected in almost every line of code that reads or writes to this mapping, square brackets are used. However there is one line of code involving a tuple that uses parentheses instead, wrapping a pair of them around msg.sender:
(,,,bool exists,,) = moloch.members(msg.sender);
Why isn't this line of code using square brackets after the moloch.members reference, like this?:
(,,,bool exists,,) = moloch.members[msg.sender];
I don't understand why that line is using parentheses and what kind of different behavior might result from this. Can someone explain this to me?
For reference purposes, this occurs inside the function below, which is a member of the MolochSummoner contract, which inherits from CloneFactory:
function registerDao(
address _daoAdress,
string memory _daoTitle,
string memory _http,
uint _version
) public returns (bool) {
moloch = Moloch(_daoAdress);
(,,,bool exists,,) = moloch.members(msg.sender);
require(exists == true, "must be a member");
require(daos[_daoAdress] == false, "dao metadata already registered");
daos[_daoAdress] = true;
daoIdx = daoIdx + 1;
emit Register(daoIdx, _daoAdress, _daoTitle, _http, _version);
return true;
}
You can only use brackets if you are accessing the variable inside the same contract.
Outside the contract, when accessing a public variable you are calling a getter function members(). Solidity automatically generates this function for you. There is no get prefix.
More about Solidity getter functions here.
This is a bit confusing and somewhat bad design decision, so I apologize.
I have a table of function references as follows:
KLC.ChatCommandBank = {
test = KLC.TestFunction,
config = KLC.OpenInterfaceOptions,
option = KLC.OpenInterfaceOptions,
options = KLC.OpenInterfaceOptions,
help = KLC.PrintHelp
};
but when f = "test" and t is a table of strings and I call
KLC.ChatCommandBank[f](t);
then the function
function KLC:TestFunction(tab)
print(tab);
end
has a nil value for tab, despite the fact that when the function is called, t is not nil.
I suspect this is due to the table of function references not having arguments defined; I haven't been able to find anything with a google and my own tinkering couldn't fix it! Any input appreciated
It's because when you define function as KLC:TestFunction(tab) it gets one implicit parameter self that refers to the table it's called on.
When you call it as KLC.ChatCommandBank[f](t), you need to explicitly pass something in place of that parameter:
KLC.ChatCommandBank[f](KLC, t)
Alternatively, you can change the definition to local function KLC.TestFunction(tab).
I have a group of functions that use Sub-Range types for their input parameter.
const
ImprovementNodeCount = 20;
SaleAllocationNodeCount = 10;
type
TImprovementNodePrintOrders = 0..ImprovementNodeCount;
TSaleAllocationNodePrintOrders = 0..SaleAllocationNodeCount;
function SaleImprovementType(PrintOrder: TImprovementNodePrintOrders): TSaleReferenceRecord;
function SaleAllocationType(PrintOrder: TSaleAllocationNodePrintOrders): TSaleReferenceRecord;
function SaleAllocationAcres(PrintOrder: TSaleAllocationNodePrintOrders): TSaleReferenceRecord;
// many more functions with different SubTypes
This has been working very well for me. I have a new situation where it would be convenient to pass one of these functions as a parameter. My sub-ranges are now causing problems because they are different types.
All of the functions look the same except for the sub-type. I tried to add a new function type like this
TGetReferenceFunction = function (Index: cardinal): TSaleReferenceRecord;
Right now the compiler complains that the types are different when I try to pass the function parameter as a TGetReferenceFunction. Is there any way to create a function type that will include all of these functions that have different sub-type parameters?
[DCC Error] SaleNameMap.pas(295): E2010 Incompatible types: 'Cardinal' and 'TImprovementNodePrintOrders'
What I really need is a type that is all numeric sub-types. I know I can create a different function type for each sub-type I have, but that still will not let me pass these functions as parameters into one common function.
I'm guessing this is not possible. If so I have some other options, but in case there is something I am missing I thought I would try here first.
If you really want one function to accept all those distinct function types, then you'll have to sacrifice type safety. You can do this with a cast:
TGetReferenceFunction(#SaleAllocationAcres)
You need to simulate a kind of anonymous method system.
For example:
// existing typed proc
function SaleAllocationType(PrintOrder: TSaleAllocationNodePrintOrders): TSaleReferenceRecord;
function SaleAllocationAcres(PrintOrder: TSaleAllocationNodePrintOrders): TSaleReferenceRecord
Type
// the prototype
SaleAllocProto = function(PrintOrder: TSaleAllocationNodePrintOrders): TSaleReferenceRecord;
// enumeration for all the existing typed procs
TSelAllocRef = (saType,saAcres);
Const
// array which references all your typed procs.
SelAllocProvider = Array[TSelAllocRef] Of TSelAllocRef = (SaleAllocationType,SaleAllocationAcres);
Then you can call
ASaleReferenceRecord := SelAllocProvider[saType](Myargument);
AnotherSaleReferenceRecord := SelAllocProvider[saAcres](Myargument)
How do I call a function that needs to be called from above its creation? I read something about forward declarations, but Google isn't being helpful in this case. What is the correct syntax for this?
Lua is a dynamic language and functions are just a kind of value that can be called with the () operator. So you don't really need to forward declare the function so much as make sure that the variable in scope when you call it is the variable you think it is.
This is not an issue at all for global variables containing functions, since the global environment is the default place to look to resolve a variable name. For local functions, however, you need to make sure the local variable is already in scope at the lexical point where you need to call the value it stores, and also make sure that at run time it is really holding a value that can be called.
For example, here is a pair of mutually recursive local functions:
local a,b
a = function() return b() end
b = function() return a() end
Of course, that is also an example of using tail calls to allow infinite recursion that does nothing, but the point here is the declarations. By declaring the variables with local before either has a function stored in it, those names are known to be local variables in lexical scope of the rest of the example. Then the two functions are stored, each referring to the other variable.
You can forward declare a function by declaring its name before declaring the actual function body:
local func1
local func2 = function()
func1()
end
func1 = function()
--do something
end
However forward declarations are only necessary when declaring functions with local scope. That is generally what you want to do, but Lua also supports a syntax more like C, in which case forward declaration is not necessary:
function func2()
func1()
end
function func1()
--do something
end
Testing under the embedded lua in Freeswitch, forward declaration does not work:
fmsg("CRIT", "It worked.")
function fmsg(infotype, msg)
freeswitch.consoleLog(infotype, msg .. "\n")
end
result:
[ERR] mod_lua.cpp:203 /usr/local/freeswitch/scripts/foo.lua:1: attempt to call global 'fmsg' (a nil value)
Reversing the order does (duh) work.
To comprehend how forward referencing in Lua works compared to C, you must understand the a fundamental difference between C compilation and the Lua execution.
In C, forward referencing is a compile time mechanism. Hence if you include a forward declaration template in a C module then any of your code following will employ this template in compiling the call. You may or may not include the function implementation in the same module, in which case both declarations must be semantically identical or the compiler will error. Since this is a compile time construct, the compiled code can be executed in any order.
In Lua, forward referencing is runtime mechanism, in that the compiled function generates a function prototype internally within the code, but this is only accessible as a runtime Lua variable or value after the execution has
passed over the declaration creating a Lua closure. Here the declaration order within the source is immaterial. It is the execution order that is important: if the closure hasn't been bound to the variable yet, then the execution will throw a "nil value" exception.If you are using a local variable to hold the function value, then normal local scoping rules still apply: the local declaration must precede its use in the source and must be within scope, otherwise the compiler will compile in the wrong global or outer local reference. So forward referencing using locals as discussed in other answer will work, but only if the Protos are bound to closures before the first call is executed.
Doesn't work for me if I try to call the function before definition. I am using this Lua script in nginx conf.
lua entry thread aborted: runtime error: lua_redirect.lua:109: attempt to call global 'throwErrorIfAny' (a nil value)
Code snippet -
...
throwErrorIfAny()
...
function throwErrorIfAny()
ngx.say("request not allowed")
ngx.exit(ngx.HTTP_OK)
end
Given some other answers have also pointed out that it didn't work for them either, it is possible that forward declaration of Lua doesn't work with other tools.
PS : It works fine if I put the function definition before and then call it after wards.
If you use OOP you can call any function member prior its "definition".
local myClass = {}
local myClass_mt = { __index = myClass }
local function f1 (self)
print("f1")
self:later() --not yet "delared" local function
end
local function f2 (self)
print("f2")
self:later() --not yet "declared" local function
end
--...
--later in your source declare the "later" function:
local function later (self)
print("later")
end
function myClass.new() -- constructor
local this = {}
this = {
f1 = f1,
f2 = f2,
later = later, --you can access the "later" function through "self"
}
setmetatable(this, myClass_mt)
return this
end
local instance = myClass.new()
instance:f1()
instance:f2()
Program output:
f1
later
f2
later