What does exit(0) do inside a recursive function? - recursion

Is there any way to exit a program inside a resursive function ? If there is a way, What will happen if I exit like that ? what does exit(0) with in a recursive function actually do ?

exit(0) will always* make the entire application exit immediately (with a status code of 0). Whether you're calling it from a recursive function or not is irrelevant — it's completely different from return.
*: well, almost always; there are a few crazy situations where it won't, but that's besides the point

Related

How do I do jumps to a label in an enclosing function in LLVM IR?

I want to do an LLVM compiler for a very old language, PL/M. This has some peculiar features, not least of which is having nested functions with the ability to jump out of an enclosing function. In pseudocode:
toplevel() {
nested() {
if (something)
goto label;
}
nested();
label:
print("finished!");
}
The constraints here are:
you can only jump into the top-level function, luckily
the stack does get unwound (the language does not support destructors, so this is easy)
you do not have to have executed the statement at label before jumping (so the naive setjmp/longjmp method doesn't work).
code at label can be executed normally, i.e. it's not like catch
LLVM has a number of non-local jump mechanisms, such as the exception handling system, but I've never used that. Can this be implemented using LLVM exceptions, or are they not suitable for this? Is there an easier way?
If you want the stack to get unwound, you'll likely want it to be in a separate function, at least a separate LLVM IR function. (The only real exception is if your language does not have a construct like C's "alloca()" and you don't allow calling a nested function by address in which case you could inline it.)
That part of the problem you mentioned, jumping out of an enclosing function, is best handled by having some way for the callee to communicate "how it exited" to the caller, and the caller having a "switch()" on that value. You could stick it in the return value (if it already returns a value, make it a struct of both values), you could add a pointer parameter that it writes to, you could add it a thread-local global variable and fill that in before calling longjmp, or you could use exceptions.
Exceptions, they're complex (I can't describe how to make them work offhand but the docs are here: https://llvm.org/docs/ExceptionHandling.html ) and slow when the exception path is taken, and really intended for exceptional situations, not for normal code. Setjmp/longjmp does the same thing as exceptions except simpler to use and without the performance trade-off when executed, but unfortunately there are miscompiles in LLVM which you need will be the one to fix if you start using them in earnest (see the postscript at the end of the answer).
Those two options cover the ways you can do it without changing the function signature, which may be necessary if your language allows the address to be taken then called later.
If you do need to take the address of nested, then LLVM supports trampolines. See https://llvm.org/docs/LangRef.html#trampoline-intrinsics . Trampolines solve the problem of accessing the local variables of the calling function from the callee, even when the function is called by address.
PS. LLVM miscompiles setjmp/longjmp today. The current model is that a call to setjmp may return twice, and only functions with the returns_twice attribute may return twice. Note that this doesn't affect the whole call stack, only the direct caller of a function that returns twice has to deal with the twice-returning call-- just because function F calls setjmp does not mean that F itself can return twice. So far, so good.
The problem is that in a function with a setjmp, all function calls may themselves call longjmp. I'd say "unless proven otherwise" as with all things in optimizers, but there is no attribute in LLVM doesnotlongjmp or any code within LLVM that attempts to answer the question of whether a function could call longjmp. Adding that would be a good optimization, but it's a separate issue from the miscompile.
If you have code like this pseudo-code:
%entry block:
allocate val
val <- 0
setjmpret <- call setjmp
br i1 setjmpret, %first setjmp return block, %second setjmp return block
%first setjmp return block:
val <- 1;
call foo();
goto after;
%second setjmp return block:
call print(val);
goto after;
%after:
return
The control flow graph shows that is no path from val <- 0 to val <- 1 to print(val). The only path with "print(val)" has "val <- 0" before it therefore constant propagation may turn print(val) into print(0). The problem here is a missing control flow edge from foo() back to the %second setjmp return block. In a function that contains a setjmp, all calls which may call longjmp must have a CFG edge to the second setjmp return block. In LLVM that control flow edge is missing and LLVM miscompiles code because of it.
This problem also manifests in the backend. The first time I heard of this problem it was in the context of the backend losing track of the placement of variables on the stack, and this issue was the underlying root cause.
For the most part setjmp/longjmp seems to work because LLVM isn't usually able to analyze what calling foo() might do and can't perform the optimization. For instance if val was not a fresh allocation but was a pointer, then who's to say that foo() doesn't have access to the same pointer, and then performs "val <- 1" on it? If LLVM can't prove that impossible, that precludes the transform to print(0). Secondly, setjmp/longjmp are just not used often in real code.

Error During Function. Where does all the data go?

I've developed a function where i use the return function to spit out a list of vectors. Unfortunately there are still a few bugs in my code. Once my function has failed due to error can i recover that list of vectors?
Functions have their own scope, so if a function fails, the function will exit and no return value will be returned. It's difficult to say what's making your function fail without looking at your code. If the failure is due to something you have control of in your code, I suggest you solve it before relying on potentially function bogus results. But if the failure is out of your control (e.g. calling an unavailable external data source) you can wrap your risky code in a try call to recover in the event of an error. I hope this helps.

Exit flag in pyOptSparseDriver

I need the ability to specify an exit flag if something failed. The OpenMDAO documentation for the pyoptsparse_driver has the option for an exit flag. However, when I run it with an exit flag as an option it says that Option 'exit_flag' has not been added. Also I am also not sure how to actually specify if something failed or not. Would I need to pass the flag out of the component that failed in the solve_nonlinear() and somehow use that to set the option on the pyoptsparse_driver? I want to do something kind of like this but I'm not sure on the syntax and I can't find an example:
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'], exit_flag = function(params['x'])
self.exit_flag = exit_flag
There are a number of issues here:
1) "How do I propagate failure information from a component up to the optimizer?"
We don't currently have a way of handling this. Its something we'll be working on in the near future though
2) If a component does fail, what is the proper response?
Depends on what you're doing. For a DOE, you should probably just log the failed case and keep going. For a gradient free method, probably some kind of objective penalization is warranted. For a gradient based algorithm, you likely need to back-track on the line-search (or use some other similar kind of walk back mechanism).
3) In the event that it all fails, can the driver report an overall exit status out.
Again, we don't have this implemented yet in a general way. The option you found in pyopt_sparse driver is a mistake in the doc-string. There is an exit_flag attribute that gets set based on the internal pyopt state though.

PreCondition or PostCondtion in ACSL

I am not able to distinguish between various precondition and post-condition in ACSL. As I know that requires, terminates and assume comes in precondition and ensures and assigns in post-condition. But in which set rest like decrease etc are??
Can any body is able to help me in figuring out??
thanks in advance
This is a trick question. Basically, decreases would serve as a pre-condition of a recursive call: if you have a function f with decreases x;, if it happens to make a call to itself, you have to prove that x<\at(x,Pre) at this call site. Additionally, you have a pre-condition that x>=0 when you call f (recursive call or not).
Regarding other clauses (based on their order of apperance in ACSL 1.7:
complete and disjoint clause are basically a logical property of the assumes clause of the contract, they do not imply anything for the implementation, but act as a sanity check of the specification itself.
allocates and frees are post-conditions (like for assigns but regarding dynamic allocation)
exits (and returns, breaks and continues) are post-conditions (they are evaluated when we exit the function -or the statement).
dependencies (\from) are post-conditions (like assigns).
decrease clause of ACSL is basically used for recursive function calls.
if you have specified decrease clause with a pointer variable x like: decrease *x;
then what it means is, every time when control enters the function related to this decrease clause, it checks whether the value pointed to by the pointer x is 1 less as compared to the value pointed to by x during the pre-state of the function. For the very first time when the function is called, pre-condition checked is: (*x) >= 0 as the function is in its pre-state so there is no pre-state value to compare to.

xquery call a maintenance function within another function

Using MarkLogic Xquery, I have a function (admin:add-collection-to-publication) which calls another maintenance function ( admin:check-collections-exists) which checks for an element's presence and if its not present then it creates that particular element.
The way I call the maintenance function is with a let. This seems like a weird way, to do this it requires creating an unused variable. Should I instead return a sequence with the call to admin:check-collections-exists being the first item in the sequence then the subsequent processing being the second element? Just looking for the standard elegant way to do this. My functions are:
declare function admin:add-collection-to-publication($pub-name, $collection-name)
{
(:does this publication have a COLLECTIONS element?:)
let $unnecessary-variable := admin:check-collections-exists($pub-name)
(:now go and do what this function does:)
return "do some other stuff then return"
};
declare function admin:check-collections-exists($pub-name)
{
if(fn:exists($pubs-node/pub:PUBLICATION[pub:NAME/text()=$pub-name]/pub:COLLECTIONS))
then
"exists"
else
xdmp:node-insert-child($pubs-node/pub:PUBLICATION[pub:NAME/text()=$pub-name],<pub:COLLECTIONS/>)
};
Using a sequence is not reliable. MarkLogic will most likely attempt to evaluate the sequence items in parallel, which could cause the creating to happen at 'same' time or even after the other work. The best approach is indeed to use a let. The let's are always evaluated before the return. Note though that let's can be evaluated in parallel as well, but the optimizer is smart enough to detect dependencies.
Personally, I often use unused variables. For example to insert logging statements, in which case I have one unused variable name that I reuse each time:
let $log := xdmp:log($before)
let $result := do:something($before)
let $log := xdmp:log($result)
You could also use a very short variable name like $_. Or you could reconsider actually giving the variable a sensible name, and use it after all, even though you know it never reaches the else
let $exists :=
if (collection-exists()) then
create()
else true()
return
if ($exists) then
"do stuff"
else () (: never reached!! :)
HTH!

Resources