Recent

Author Topic: Limit variable scope  (Read 15029 times)

Kays

  • Hero Member
  • *****
  • Posts: 624
  • Whasup!?
    • KaiBurghardt.de
Limit variable scope
« on: September 07, 2015, 11:58:26 pm »
How can I limit a variable's scope to a _block_? I'd like to write something like the following but it throws

Code: [Select]
c.pas(5,3) Error: Illegal expression
c.pas(6,4) Fatal: Syntax error, ";" expected but "identifier I" found

Code: [Select]
program c;
begin
write('hello world');
begin
var // this is illegal
i: integer; // that's the fatal syntax error: ";" expected but "identifier I" found
i := 3;
while i > 0 do
begin
write('!');
dec(i);
end;
end;
writeln;
end.
Yours Sincerely
Kai Burghardt

derek.john.evans

  • Guest
Re: Limit variable scope
« Reply #1 on: September 08, 2015, 12:14:49 am »
Create new procedure/function.

Thaddy

  • Hero Member
  • *****
  • Posts: 18328
  • Here stood a man who saw the Elbe and jumped it.
Re: Limit variable scope
« Reply #2 on: September 08, 2015, 07:16:08 am »
Create it inlined to obtain block local scoping:
Code: [Select]
program p;
{apptype console}{$i-}
procedure scoped;inline;
var
  i: integer;
begin
  i := 3;
  while i > 0 do
  begin
    write('!');
    dec(i);
  end;
end;
begin
  write('hello world');
  begin
    scoped;// code will be inlined here, if possible. no call to procedure
  end;
  writeln;
end.
« Last Edit: September 08, 2015, 07:56:36 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Kays

  • Hero Member
  • *****
  • Posts: 624
  • Whasup!?
    • KaiBurghardt.de
Re: Limit variable scope
« Reply #3 on: September 13, 2015, 12:52:14 am »
Yeah, introducing a new procedure is one way. But I want to limit the scope to a block. That's why I emphasized _block_ in my OP.

Using a procedure means, it's going to reserve a whole new context on the stack, eh? I don't want this.

So there's the inline modifier copying the procedure's body to the place where it's called. Huh. Uhm. That's a sub-optimal solution: Normally you'd introduce procedures if they're either called multiple times or they serve a well-defined task. This is not necessarily the case.
« Last Edit: September 13, 2015, 01:01:36 am by Kays »
Yours Sincerely
Kai Burghardt

derek.john.evans

  • Guest
Re: Limit variable scope
« Reply #4 on: September 13, 2015, 02:22:46 am »
Using a procedure means, it's going to reserve a whole new context on the stack, eh? I don't want this.

Yes, and no. Procedures defined in procedures have access to their parents variables and parameters.

Normally you'd introduce procedures if they're either called multiple times or they serve a well-defined task. This is not necessarily the case.

I think this has been discussed before. Yes, other languages have "incode" variable defines. No, Pascal does not. Ive never found it an issue. I guess, my view is, Pascal is a beautiful thing, and if you want other language styles, then code in other languages.

There is something about Pascal which protects me from doing stupid things, and I need that. Me and C++, are just trouble.

NOTE: Here is a inner procedure example. I use this a lot when I want a block of code with new variables, which is only used inside one procedure.
Code: [Select]
  procedure Test;

    procedure Loop;
    var
      I: Integer;
    begin
      I := 3;
      while I > 0 do begin
        write('!');
        dec(I);
      end;
    end;
  begin
    write('hello world');
    Loop;
    writeln;
  end; 
« Last Edit: September 13, 2015, 02:24:36 am by Geepster »

Thaddy

  • Hero Member
  • *****
  • Posts: 18328
  • Here stood a man who saw the Elbe and jumped it.
Re: Limit variable scope
« Reply #5 on: September 13, 2015, 11:21:29 am »
Yeah, introducing a new procedure is one way. But I want to limit the scope to a block. That's why I emphasized _block_ in my OP.

Using a procedure means, it's going to reserve a whole new context on the stack, eh? I don't want this.

So there's the inline modifier copying the procedure's body to the place where it's called. Huh. Uhm. That's a sub-optimal solution: Normally you'd introduce procedures if they're either called multiple times or they serve a well-defined task. This is not necessarily the case.

No!@@! I explained that by declaring the procedure *inline* you achieve *block* scoping, as can be seen from the assembler output. If it is just the eye candy of just *declaring* a variable in block scope? That doesn't add any value regarding generated code efficiency and there are plugins available for *editors* that can do just that for Delphi. I am not sure about Lazarus, but I won't be surprised if it is available.  The advantage over C's lazy typing is that in Pascal a separate procedure leads to easier to maintain sourcecode. Which is, btw, of course also possible in modern C.
There is no obvious reason to add bad coding habits to Pascal, imnsho.
« Last Edit: September 13, 2015, 11:29:55 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12527
  • FPC developer.
Re: Limit variable scope
« Reply #6 on: September 13, 2015, 12:44:42 pm »
Yeah, introducing a new procedure is one way. But I want to limit the scope to a block. That's why I emphasized _block_ in my OP.

Using a procedure means, it's going to reserve a whole new context on the stack, eh? I don't want this.

Yes, but inline that might optimize away. And 64-bit doesn't even need a stack frame in many situations.

Most compilers will simply allocate one single frame anyway, since reserving them locally would only cost extra instructions. So declarative behaviour an code generated are not 1:1 anyway, except maybe codegenerators for extremely limited architectures.



Basile B.

  • Guest
Re: Limit variable scope
« Reply #7 on: September 13, 2015, 04:44:01 pm »
If the variable is a class it's possible to use the with and the try finally statements to mimic a scoped variable:

Code: [Select]
with TMemoryStream.create do
try
  // awesome code for the scoped instance
finally
  free;
end;

A note that's a bit off-topic: from the machine code point of view the scope doesn't exist. Usually ESP is decremented for all the variables in a SUB at the beginning.

Thaddy

  • Hero Member
  • *****
  • Posts: 18328
  • Here stood a man who saw the Elbe and jumped it.
Re: Limit variable scope
« Reply #8 on: September 13, 2015, 04:45:02 pm »
@Marco: thanks for explaining the compiler will optimize the stack anyway. That is also obvious from the assembler output, which is coherent between multiple (language) compilers.

I suggest to check this (not to you, Marco) by compiling with -a added and checking the generated code.
I also hinted that when the compiler is not able to inline the code can be worse than expected. This goes for other compilers too. But I am afraid the question was more in the frivolous part of what is possible syntax wise and not about efficient coding.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Thaddy

  • Hero Member
  • *****
  • Posts: 18328
  • Here stood a man who saw the Elbe and jumped it.
Re: Limit variable scope
« Reply #9 on: September 13, 2015, 04:48:07 pm »
If the variable is a class it's possible to use the with and the try finally statements to mimic a scoped variable:

Code: [Select]
with TMemoryStream.create do
try
  // awesome code for the scoped instance
finally
  free;
end;

A note that's a bit off-topic: from the machine code point of view the scope doesn't exist. Usually ESP is decremented for all the variables in a SUB at the beginning.
Correct.

About your last statement, which of course you know already the answer, but needs to be clear:
That is implementation and differs a lot between compilers, even in the same high level language. FPC does a pretty good job in this case.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12527
  • FPC developer.
Re: Limit variable scope
« Reply #10 on: September 13, 2015, 05:52:12 pm »
Yes, I know. I even experimented this because since two years I use a compiler (DMD) that often generates ENTER <SIZE> instead of the usuall SUB ESP <SIZE>. The first time i've seen that I was shocked.

Yeah, because afaik every optimization manual says "enter" is slower on anything since P-I.

See e.g. http://stackoverflow.com/questions/5959890/enter-vs-push-ebp-mov-ebp-esp-sub-esp-imm-and-leave-vs-mov-esp-ebp

Note the last answer about displays.

Do you use "size more important than speed" settings with that other compiler, or is it really ancient?

Basile B.

  • Guest
Re: Limit variable scope
« Reply #11 on: September 13, 2015, 06:58:07 pm »
Yes, DMD backend is based on the Symantec C++ compiler's one, so 20 year old. But that's only the backend. The language itself is quite modern.

enter is generated here:
https://github.com/D-Programming-Language/dmd/blob/e9808b5f7cbf4ae147e39c6aa8230ca2b1aef735/src/backend/cgcod.c#L856

after a quick check in the blame i can say that this particular feature has almost never changed since it was put on github.

BeniBela

  • Hero Member
  • *****
  • Posts: 947
    • homepage
Re: Limit variable scope
« Reply #12 on: September 15, 2015, 01:06:41 pm »

There is something about Pascal which protects me from doing stupid things, and I need that. Me and C++, are just trouble.

But there is not enough protection.

No protection against using a variable where it does not make sense.

E.g. It happens all the time that there is a loop, and a variable that is only used within the loop, and then you can still use the variable after the loop. No warning, no hint, and your program is broken due to a bug that could be automatically detected.

A language without block-scope variables is almost as primitive    as a language that only has (thread) global variables.


Thaddy

  • Hero Member
  • *****
  • Posts: 18328
  • Here stood a man who saw the Elbe and jumped it.
Re: Limit variable scope
« Reply #13 on: September 15, 2015, 01:13:18 pm »

There is something about Pascal which protects me from doing stupid things, and I need that. Me and C++, are just trouble.

But there is not enough protection.

No protection against using a variable where it does not make sense.

E.g. It happens all the time that there is a loop, and a variable that is only used within the loop, and then you can still use the variable after the loop. No warning, no hint, and your program is broken due to a bug that could be automatically detected.

A language without block-scope variables is almost as primitive    as a language that only has (thread) global variables.

I might add to that by explaining that Pascal is sufficiently expressive to shoot yourself in the foot. You are just not as likely to do it as with C or C++, but you can. I know...

And you are still not differentiating between eye candy and generated code. The C code with msvc and gcc is similar to that from fpc. I wish you properly checked that first.
« Last Edit: September 15, 2015, 01:16:01 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

derek.john.evans

  • Guest
Re: Limit variable scope
« Reply #14 on: September 15, 2015, 01:44:30 pm »

There is something about Pascal which protects me from doing stupid things, and I need that. Me and C++, are just trouble.
A language without block-scope variables is almost as primitive as a language that only has (thread) global variables.

I don't understand these topics. If you want C/C++/C#/Java, then use those languages.

The world is yours to explore!

 

TinyPortal © 2005-2018