SRL Archive - Lape

Infinite loop thing


Gu3st...

2014-05-14 19:59:59

begin
while True do
'Someone tell me what''s going on here...'
end.

E: To specify: I understand what is going on and why it is doing so; what I'm trying to accomplish with this thread is getting an answer on why la-pe was designed this way instead of returning an error.

rj

2014-05-14 20:19:10

How does that even compile lol?

Hoodz

2014-05-14 20:27:16


begin
while True do
begin
writeln('Someone tell me what''s going on here...');
exit;
end;
end.

:D

Janilabo

2014-05-14 20:30:50

If you are pointing to "while True do" part being an infinite loop, it is not a bug.
True is obviously always true - so it just keeps going on, which is logical.
..just like you can see sometimes use of "until False;" with repeat loop (this is the same thing for while loops)! :p

Gu3st...

2014-05-14 20:37:13

The code compiles, which I find weird, nothing more, nothing less :p

From: Robert
How does that even compile lol?

Exacly, heh

Janilabo

2014-05-14 20:53:58

@Zyt3x
Ahhh, sorry mate.. I thought you were talking about the infinite loop.

This here compiles:
begin
'Someone tell me what''s going on here...'
end.

..and so does this:
begin
while True do
end.

The second one also compiles in PascalScript.. So is the bug the first example? O_o

Gu3st...

2014-05-14 21:01:52

From: Janilabo
@Zyt3x
Ahhh, sorry mate.. I thought you were talking about the infinite loop.

This here compiles:
begin
'Someone tell me what''s going on here...'
end.

..and so does this:
begin
while True do
end.

The second one also compiles in PascalScript.. So is the bug the first example? O_o

Well, it's not really a bug per-se, but it's weird looking :p

Imo it should throw an error or something

Brandon

2014-05-14 22:14:26

None of the above is a bug and it should never throw..

Here's why:


'dsgsgsgs';

is actually declaring a constant compile time string. The string may not be used but it is certainly created. Compile time calculations and storage is actually a GOOD thing (most of the time.. not always). C++ and Assembly makes heavy use of this.

If you do:



int main()
{
"hello there";
return 0;
}


in any C compiler, you will notice that it compiled.. The assembly generated however would be different:


main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret


In other words, the string that is created is actually not stored in the .data section because it is un-used and so the compiler optimises it out..

However, if you were to assign the string to a variable and use that variable, it will be stored in the .data section and the variable would hold the address of it.

The same exact logic applies to Simba. The string is created. Is it optimised out? I have no clue because we cannot currently view Simba's assembly. What I do know is this:


var
str, str2: String;
begin
str := 'hello'
str2 := str;
end;


Both str2 and str1 point to a constant string 'hello' that is stored somewhere (.data section for simba scripts). The reference count is thus "-1" for constants.. If the two strings were dynamically allocated (run-time), then str2 would still point to str1.. however, the reference would be "2" because 2 variables point to the same memory location..


When str2 is changed or str1 is changed, a new string might be allocated instead (run-time). If neither are changed, they should both be pointing to the exact same (compile-time) string if and only if Simba has that sort of optimisation.. Otherwise, they'd be pointing to two separate compile time strings..

Because of this logic, that constant string within your loop.. isn't created every single time. Instead, it is created only ONCE no matter how many times you loop. It is created at the start of your script..


You can verify this logic by doing:



var
str1, str2: String;
begin
str1 := 'hello';
str2 := str1;

(@Str1[1])^ := 'm';

writeln(str1); //prints 'mello'
writeln(str2); //prints 'mello'
end.

You ask why? Because like I said.. they both point to the exact same address! str2 is NOT a copy of str1!

Now here is the trick:



var
str1, str2: String;
begin
str1 := 'hello';
str2 := str1;

str1[1] := 'm';

writeln(str1); //prints 'mello'
writeln(str2); //prints 'hello'
end.

WTH? You ask? Well.. like I said. When one is "changed", a COPY is made and all changes are made to that COPY! This is known as "copy-on-write".


Now that you know how the optimisation side works.. THIS IS A GOOD THING.. This guarantees that your scripts run fast! Only ONE string is created because the compiler is smart enough to know that you're not changing it and that you're using the same string every loop. I thus believe that it will optimise out your string if it is unused. I'm sure you'll agree now that it shouldn't be removed and shouldn't throw.


Now for the loop:

The assembly for the loop however would look like:


main:
push rbp
mov rbp, rsp

.while_jump: ;begin loop

;the body of the loop goes here..

jmp .while_jump ;continue loop infinitely

It will simply "stall" the CPU and wait infinitely. Without a "sleep/wait", it "can possibly" use 100% CPU.

Gu3st...

2014-05-15 02:17:23

From: Brandon
None of the above is a bug and it should never throw..

Here's why:


'dsgsgsgs';

is actually declaring a constant compile time string. The string may not be used but it is certainly created. Compile time calculations and storage is actually a GOOD thing (most of the time.. not always). C++ and Assembly makes heavy use of this.

If you do:



int main()
{
"hello there";
return 0;
}


in any C compiler, you will notice that it compiled.. The assembly generated however would be different:


main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret


In other words, the string that is created is actually not stored in the .data section because it is un-used and so the compiler optimises it out..

However, if you were to assign the string to a variable and use that variable, it will be stored in the .data section and the variable would hold the address of it.

The same exact logic applies to Simba. The string is created. Is it optimised out? I have no clue because we cannot currently view Simba's assembly. What I do know is this:


var
str, str2: String;
begin
str := 'hello'
str2 := str;
end;


Both str2 and str1 point to a constant string 'hello' that is stored somewhere (.data section for simba scripts). The reference count is thus "-1" for constants.. If the two strings were dynamically allocated (run-time), then str2 would still point to str1.. however, the reference would be "2" because 2 variables point to the same memory location..


When str2 is changed or str1 is changed, a new string might be allocated instead (run-time). If neither are changed, they should both be pointing to the exact same (compile-time) string if and only if Simba has that sort of optimisation.. Otherwise, they'd be pointing to two separate compile time strings..

Because of this logic, that constant string within your loop.. isn't created every single time. Instead, it is created only ONCE no matter how many times you loop. It is created at the start of your script..


You can verify this logic by doing:



var
str1, str2: String;
begin
str1 := 'hello';
str2 := str1;

(@Str1[1])^ := 'm';

writeln(str1); //prints 'mello'
writeln(str2); //prints 'mello'
end.

You ask why? Because like I said.. they both point to the exact same address! str2 is NOT a copy of str1!

Now here is the trick:



var
str1, str2: String;
begin
str1 := 'hello';
str2 := str1;

str1[1] := 'm';

writeln(str1); //prints 'mello'
writeln(str2); //prints 'hello'
end.

WTH? You ask? Well.. like I said. When one is "changed", a COPY is made and all changes are made to that COPY! This is known as "copy-on-write".


Now that you know how the optimisation side works.. THIS IS A GOOD THING.. This guarantees that your scripts run fast! Only ONE string is created because the compiler is smart enough to know that you're not changing it and that you're using the same string every loop. I thus believe that it will optimise out your string if it is unused. I'm sure you'll agree now that it shouldn't be removed and shouldn't throw.


Now for the loop:

The assembly for the loop however would look like:


main:
push rbp
mov rbp, rsp

.while_jump: ;begin loop

;the body of the loop goes here..

jmp .while_jump ;continue loop infinitely

It will simply "stall" the CPU and wait infinitely. Without a "sleep/wait", it "can possibly" use 100% CPU.
Wow, just wow. Thank you for that thorough explanation! :D Very much appreciated!!
Something like this is exactly what I was looking for when I created this thread, and boy did you deliver!
+1 rep :)

E:
You must spread some Reputation around before giving it to Brandon again.