Catching exceptions from a loop - forth

I'm trying to write a Forth word which will drop all items on the stack. I'm using a pretty dumb method, by running an infinite loop with 'drop' and catching the error when 'drop' fails because the stack is empty.
My words are defined as such:
( Infinite drop loop)
: droploop begin drop true while drop repeat ;
( Experimental catch with a single drop)
: dropcatcher ['] drop catch drop ;
( Like dropcatcher, but with 'droploop' instead of 'drop')
: dropall ['] droploop catch drop ;
When I run droploop, I get an error like I'd expect and after execution, the stack is empty.
When I run dropcatcher, it drops if the stack isn't empty, and if the stack is empty it reports nothing.
When I run dropall, I get all sorts of stuff leftover on the stack.
It looks like this:
2 3 4 5 6 7 8 9 10 dropall .s <9> -1 3 -1 5 -1 7 -1 9 -1 ok
I'd expect that dropall would simply clear the stack without complaint because droploop and dropcatcher seem to work right by themselves, but alas, I don't understand why dropall isn't working.
Why does dropall seem to work differently than droploop and dropcatcher? Or, what I'm I doing wrong here?

When droploop throws an error, it will probably call ABORT or -1 THROW, which by definition clears the data stack. So it may well be that droploop doesn't drop the right number of stack items before the error is detected, but the system exception handler does it for you.
When I run droploop myself, it either crashes or hangs. This would seem to confirm my theory that there is a severe stack underflow.
As for the state of the stack after dropall, my guess would be that gforth maybe doesn't detect the stack underflow at the right time, and what you're seeing is some semi-random garbage. Hence this is what droploop leaves on the stack before calling ABORT.
Side note: Your droploop drops two stack items every iteration, which may or may not be what you intended. Also, use again for an endless loop instead of true while. I.e. : droploop begin drop again;
Of course, a better way to clear the stack would be
: clear depth 0 ?do drop loop ;
or
: clear begin depth while drop repeat ;
or
: clear sp0 sp! ;

Related

How to break from a loop in Maxima

I am new to Maxima. I am trying to write a loop in that I am checking if some condition met then exit from the loop.
cp:for i:1 step 1 thru 10 do
block(if(i>6) then break()
else
print(i,"is less than 6"));
I want output:
1 is less than 6
2 is less than 6
3 is less than 6
4 is less than 6
5 is less than 6
6 is less than 6
But when I am running the above code :
after printing 6 is less than 6, it is prompting
Entering a Maxima break point. Type 'exit;' to resume.
and after typing exit; it will again show the above msg
I want the code will come out completely from that loop rather than asking to type exit;
Thank you in advance..
Try return(i) instead of break(). Also, return only returns from the block which encloses it, so you need to remove the block(...) in your example (it's unneeded anyway). I think this works:
cp: for i:1 step 1 thru 10
do if(i>6) then return(i) else print(i,"is less than 6");

Is there a reason why this code is not outputting a worth

Problem
Hello, StackOverflow community! I am working on this Lua game, and I was testing to see if it would change the text on my TextLabel to the Bitcoins current worth, I was utterly disappointed when nothing showed up.
I have tried to do research on Google, and my code seems to be just right.
Code
Change = false
updated = false
while Change[true] do --While change = true do
worth = math.random(1,4500) --Pick random number
print('Working!') --Say its working
Updated = true --Change the updated local var.
end --Ending while loop
script.Parent.TextLabel.Text.Text = 'Bitcoin is currently worth: ' .. worth
--Going to the Text, and changing in to a New worth.
while Updated[false] do --While updated = false do
wait(180) --Wait
Change = true --After waits 3 minutes it makes an event trigger
end -- Ending while loop
wait(180) --Wait
Updated = false --Reseting Script.
I expect the output on the Label to be a random number.
I can't really speak to roblox, but there are a couple of obvious problems with your code:
Case
You have confusion between capitalized ("Updated", "Change") and lowercase ("updated", "change" [in commented while statement]), which will fail. See, for example:
bj#bj-lt:~$ lua
Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> Updated = true
> print(Updated)
true
> print(updated)
nil
So be super-careful about what identifiers you capitalize. In general, most programmers leave variables like that in all-lowercase (or sometimes things like camelCase). I suppose there might be some oddball lua runtime out there that is case-insensitive, but I don't know of one.
Type misuse.
Updated is a boolean (a true/false value), so the syntax:
while Change[true] do
...is invalid. See:
> if Updated[true] then
>> print("foo")
>> end
stdin:1: attempt to index global 'Updated' (a boolean value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
Note also that the "While change == true do" is also wrong because of case ("While" is not valid lua, but "while" is).
Lastly:
Lack of threading.
You have basically two different things that you're trying to do at once, namely randomly change the "worth" variable as fast as possible (it's in a loop) and see a set a label to match it (it looks like you probably want it to change constantly). This requires two threads of operation (one to change worth and another to read it and stick it on the label). You've written this like you're assuming you have a spreadsheet or something and that. What your code is actually doing is:
Setting some variables
Updating worth indefinitely, printing 'Working!' a bunch, and...
Never stopping
The rest of the code never runs, because the rest of the code isn't in a background thread (basically the first bit monopolizes the runtime and never yields to everything else).
Lastly, even if the top code was running in the background, you only set the Text label one-time to exactly "Bitcoin is currently worth: 3456" (or some similar number) one time. The way this is written there won't be any updates thereafter (and, if it runs once before the other thread has warmed up, it might not be set to anything useful at all).
My guess is that your runtime is spitting out errors left and right due to the identifier problems and/or is running in a tight infinite loop and never actually getting to the label refresh logic.
BJ Black has given an excellent description of the issues with the syntax, so I'll try to cover the Roblox piece of this. In order for this kind of thing to work properly in a Roblox game, here are some assumptions to double check :
Since we are working with a TextLabel, is it inside a ScreenGui? Or a SurfaceGui?
If it's in a ScreenGui, make sure that ScreenGui is in StarterGui, and is this code in a LocalScript
If it's in a SurfaceGui, make sure that SurfaceGui is adorning a Part and this code
is in a Script
After you checked all those pieces, maybe this is closer to what you were thinking :
-- define the variables we're working with
local textLabel = script.Parent.TextLabel
local worth = 0
-- create an infinite loop
spawn(function()
while true do
--Pick random number
worth = math.random(1,4500)
-- update the text of the label with the new worth
textLabel.Text = string.format("Bitcoin is currently worth: %d", worth)
-- wait for 3 minutes, then loop
wait(180)
end
end)
I removed Updated and Changed because all they were doing was deciding whether or not to change the value. The flow of your loop was:
do nothing and display an undefined number. Wait 3 minutes
update the number, display it, wait 6 minutes
repeat 1 and 2.
So hopefully this is a little clearer and closer to what you were thinking.

How to pop Nth item in the stack [Befunge-93]

If you have the befunge program 321&,how would you access the first item (3) without throwing out the second two items?
The instruction \ allows one to switch the first two items, but that doesn't get me any closer to the last one...
The current method I'm using is to use the p command to write the entire stack to the program memory in order to get to the last item. For example,
32110p20p.20g10g#
However, I feel that this isn't as elegant as it could be... There's no technique to pop the first item on the stack as N, pop the Nth item from the stack and push it to the top?
(No is a perfectly acceptable answer)
Not really.
Your code could be shortened to
32110p\.10g#
But if you wanted a more general result, something like the following might work. Below, I am using Befunge as it was meant to be used (at least in my opinion): as a functional programming language with each function getting its own set of rows and columns. Pointers are created using directionals and storing 1's and 0's determine where the function was called. One thing I would point out though is that the stack is not meant for storage in nearly any language. Just write the stack to storage. Note that 987 overflows off a stack of length 10.
v >>>>>>>>>>>12p:10p11pv
1 0 v<<<<<<<<<<<<<<<<<<
v >210gp10g1-10p^
>10g|
>14p010pv
v<<<<<<<<<<<<<<<<<<<<<<<<
v >210g1+g10g1+10p^
>10g11g-|
v g21g41<
v _ v
>98765432102^>. 2^>.#
The above code writes up to and including the n-1th item on the stack to 'memory', writes the nth item somewhere else, reads the 'memory', then pushes the nth item onto the stack.
The function is called twice by the bottom line of this program.
I propose a simpler solution:
013p 321 01g #
☺
It "stores" 3 in the program at position ☺ (0, 1) (013p), removing it from the stack, and then puts things on the stack, and gets back ☺ on top of the stack (01g). The # ensures that the programs finishes.

Return stack operations generate "invalid memory address" in Gforth 0.7

I'm learning Forth here, and I've got onto return stack operations.
So using the console on Ubuntu 11.04 x64 I am trying to get the TOS onto the return stack but this happens:
1 2 3 4 5 ok
>r
:36: Invalid memory address
>R>>><<<
Backtrace:
What am I doing wrong here?
>r is itself a word and needs to return to the interpreter. When >r is executed as in the question it adds a new return address, an invalid one.
Instead use >r inside a (new) word. Note that the items added to the return stack must be removed before that word ends - the return stack must be in the same state as when the word started executing.
Loops are actually an example of an application of the return stack inside words (and thus your own use of the return stack must also be balanced within loops just as it must be balanced within a word).
What you are trying to to do doesn't really make much sense. A forth machine executes a series of words, the address of the next word in line to be executed is stored in a special register called NEXT (think of it like the instruction pointer of a CPU).
A return stack is needed because, if a call is made to a word that is itself a threaded list of words, then you would end up scrubbing the original address in NEXT register - to stop this from happening, the current contents of the NEXT register are pushed into the return stack.
If I understand correctly >r pushes the top element of the data stuck onto the return stack; in this case, '5' is not valid, because, there are no instructions at the address '5'.
As someone else has pointed out you don't need to be concerned about the return stack, unless you are implementing new control constructs.
You can use the return stack in Gforth in the command line (that's a non-standard feature), with one limitation: It has to be balanced within one line. At the end of the line, the line interpreter is going to return, and therefore, the return stack must contain the expected return address.
So try something like
1 2 3 4 5 >r + r> .s
which should give you
1 2 7 5

Is there a safe way to clean up stack-based code when jumping out of a block?

I've been working on Issue 14 on the PascalScript scripting engine, in which using a Goto command to jump out of a Case block produces a compiler error, even though this is perfectly valid (if ugly) Object Pascal code.
Turns out the ProcessCase routine in the compiler calls HasInvalidJumps, which scans for any Gotos that lead outside of the Case block, and gives a compiler error if it finds one. If I comment that check out, it compiles just fine, but ends up crashing at runtime. A disassembly of the bytecode shows why. I've annotated it with the original script code:
[TYPES]
<SNIPPED>
[VARS]
Var [0]: 27 Class TFORM
Var [1]: 28 Class TAPPLICATION
Var [2]: 11 S32 //i: integer
[PROCS]
Proc [0] Export: !MAIN -1
{begin}
[0] ASSIGN GlobalVar[2], [1]
{ i := 1;}
[15] PUSHTYPE 11(S32) // 1
[20] ASSIGN Base[1], GlobalVar[2]
{ case i of}
[31] PUSHTYPE 25(U8) // 2
{ 0:}
[36] COMPARE into Base[2]: [0] = Base[1]
[57] COND_NOT_GOTO currpos + 5 Base[2] [72]
{ end;}
[67] GOTO currpos + 41 [113]
{ 1:}
[72] COMPARE into Base[2]: [1] = Base[1]
[93] COND_NOT_GOTO currpos + 10 Base[2] [113]
{ goto L1;}
[103] GOTO currpos + 8 [116]
{ end;}
[108] GOTO currpos + 0 [113]
{ end; //<-- case}
[113] POP // 1
[114] POP // 0
{ Exit;}
[115] RET
{L1:
Writeln('Label L1');}
[116] PUSHTYPE 17(WideString) // 1
[121] ASSIGN Base[1], ['????????']
[144] CALL 1
{end.}
[149] POP // 0
[150] RET
Proc [1]: External Decl: \00\00 WRITELN
The "goto L1;" statement at 103 skips the cleanup pops at 113 and 114, which leaves the stack in an invalid state.
Delphi doesn't have any trouble with this, because it doesn't use a calculation stack. PascalScript, though, is not as fortunate. I need some way to make this work, as this pattern is very common in some legacy scripts from a much simpler system with little in the way of control structures that I've translated to PascalScript and need to be able to support.
Anyone have any ideas how to patch the codegen so it'll clean up the stack properly?
IIRC the goto rules in classic pascals were:
jumps are only allowed out of a block (iow from a higher to a lower nesting level on the "same" branch of the tree)
from local procedures to their parents.
The later was afaik never supported by Borland derived Pascals, but the first still holds.
So you need to generate exiting code like Martin says, but possibly it can be for multiple block levels, so you can't have a could codegeneration for each goto, but must generate code (to exit the precise number of needed blocks).
A typical test pattern is to exit from multiple nested ifs (possibly within a loop) using a goto, since that was a classic microoptimization that was faster at least up to D7.
Keep in mind that the if evaluation(s) and the begin..end blocks of their branches might have generated temps that need cleanup.
---------- added later
I think the codegenerator needs a way to walk the scopes between the goto and its endpoint, generating the relevant exit code for blocks along the way. That way a fix works for the general case and not just this example.
Since you can only jump out of scopes, and not into it that might not that be that hard.
IOW generate something that is equivalent to (for a hypothetical double case block)
Lgoto1gluecode:
// exit code first block
pop x
pop y
// exit code first block
pop A
pop B
goto real_goto_destination
Additional analysis can be done. E.g. if there is only one scope, and it has already a cleanup exit label, you can jump directly. If you know for certain that the above pop's are only discarded values (and not saves of registers) you can do them at once with add $16,%esp (4*4 byte values) etc.
The straightforward solution would be:
When generating a GOTO for goto statement, prefix the GOTO with the same cleanup code that comes before RET.
It looks to me like the calculation of how far to jump forward is the problem. I would have to spend some time looking at the implementation of the parser to help further, but my guess would be that additional handling must be performed when using a goto and there are values on the stack AND the goto would be placed after those values would be removed from the stack. Of course to determine this you would need to save the current location being parsed (the goto) and the forward parse to the target location watching for stack changes, and if so then to either adjust the goto location backwards, or inject the code as Martin suggested.

Resources