Page 1 of 1

Can't put adress of label into a static

Posted: Thu Jun 11, 2009 9:06 pm
by Trond

Code: Select all

Procedure T()
  Static *Table.Character = ?Table
  Table:
EndProcedure
?Table can be computed at compile time. Is it a bug?

Posted: Thu Jun 11, 2009 9:10 pm
by dell_jockey
will an address fit into a '.Character' variable?

Posted: Thu Jun 11, 2009 9:11 pm
by Trond
It was a typo, I forgot the *.

Posted: Thu Jun 11, 2009 9:50 pm
by Kaeru Gaman
Constants work and the Help also states it has to be a constant value, not a literal value.

but since the compiler works one-pass, adresses of labels later in the code can't be known in this step.

you also can't assign a label to a constant.


... I guess you'll need to screw a workaround.

Posted: Fri Jun 12, 2009 6:43 am
by eesau
Kaeru Gaman wrote:but since the compiler works one-pass, adresses of labels later in the code can't be known in this step.
That's not true, this works:

Code: Select all

Debug ?Label

Label:
... because it's FASM that gets the address, not PB. Also, Trond's code works if Protected is used.

Posted: Fri Jun 12, 2009 8:46 am
by Demivec
eesau wrote:
Kaeru Gaman wrote:but since the compiler works one-pass, adresses of labels later in the code can't be known in this step.
That's not true, this works:

Code: Select all

Debug ?Label

Label:
... because it's FASM that gets the address, not PB. Also, Trond's code works if Protected is used.
It also works like this:

Code: Select all

Global *Table.Character = ?Table

Procedure T()
  Shared *Table.Character
  Table:
EndProcedure
or like this:

Code: Select all

Procedure T()
  Static *Table.Character
  If *Table = 0
    *Table = ?Table
  EndIf
  
  Table:
EndProcedure
The hangup is that Static can only accept a literal or defined constant. If it could accept a computed constant (determined at compile time) it would work with your first example Trond. It isn't directly limited by label's.

You can't assign a label to a defined constant either (i.e. #constant = ?Table), I tried. Label's fall into the category of a variable whose value is determined at compile-time. As eesau pointed out they're value is determined by FASM and not PB.

Posted: Fri Jun 12, 2009 12:35 pm
by Trond
The hangup is that Static can only accept a literal or defined constant. If it could accept a computed constant (determined at compile time) it would work with your first example Trond. It isn't directly limited by label's.
No, it is in fact directly limited by labels. I don't understand what you're saying. It works with every other constant in scope except labels.

See?

Code: Select all

Procedure Test()
  Static M = #PI + 5.5
EndProcedure
Label's fall into the category of a variable whose value is determined at compile-time.
They are not variables! They can't ever vary, they are constants. And since they are determined at compile time there is no real reason they can't be used with Static variables.

Posted: Fri Jun 12, 2009 1:33 pm
by Demivec
Trond wrote:
The hangup is that Static can only accept a literal or defined constant. If it could accept a computed constant (determined at compile time) it would work with your first example Trond. It isn't directly limited by label's.
No, it is in fact directly limited by labels. I don't understand what you're saying. It works with every other constant in scope except labels.

See?

Code: Select all

Procedure Test()
  Static M = #PI + 5.5
EndProcedure
Label's fall into the category of a variable whose value is determined at compile-time.
They are not variables! They can't ever vary, they are constants. And since they are determined at compile time there is no real reason they can't be used with Static variables.

It's easy to understand, let me attempt a better explanation.

*Disclaimer: the following details about PureBasic are theorized and not known as fact.

Ignoring procedures for the moment, why does this code fail when using using constants?

Code: Select all

m = #MyConstant + 5.5
#MyConstant = 12
It fails because PureBasic is a one-pass compiler, the constant needs to be defined before it's used.

If that's true (with constants) than why does the following compile?

Code: Select all

m = ?Table + 5

DataSection
  Table:
  Data.l 1,2,3
EndDataSection
It compiles because labels are "special variables." The compiler set's aside space for them when they are first encountered even though it doesn't know their value yet. It knows their value will never change, but unlike an undefined constant, it doesn't know the value yet. Unlike other variable it knows what the type (and thus size) that the value will be. The value is defined as a label and the label is placed in the compiled code (which will be run later on a multi-pass assembler) at that point. When the label definition is encountered later it is added to the DataSection portion that will be added at the end, after all the compiled code.

The same process happens even when a label definition appears before it's first use.

What does this mean? Labels can be thought of as either "special constants" or "special variables". They do not receive a constant value by the compiler, they receive it from the assembler.

If that failed to make sense or you simply think I missed the boat (wouldn't be the first time I did), I'll leave the matter as it is and wish you well in solving it.:wink:

I think what you are needing is a feature request.

Posted: Fri Jun 12, 2009 8:27 pm
by Trond
*Disclaimer: the following details about PureBasic are theorized and not known as fact.
You can get the actual facts from the asm file, and your description of what happens isn't right. There is no space allocated to store the value of the label.
In this code:

Code: Select all

var = ?label
label:
PB turns ?label into l_label and label into l_label as well, like this:

Code: Select all

mov dword [v_var], l_label
l_label:
Then the assembler replaces l_label with the address of l_label: (which is simply a number).

This is the same code that is generated for numbers (var = 123):

Code: Select all

mov dword [v_var], 123
But not the same code that is generated for variables (var = othervar), which have space set aside for them. They have to be moved onto the cpu first:

Code: Select all

mov ecx, dword [v_othervar]
mov dword [v_var], ecx
Thus it's not possible to use this form for Static.

When the compiler sees (Static varname = 123) it currently writes this to the near end of the asm file:

Code: Select all

s_Procname.v_varname dd 123
All that is needed to support this feature is to replace ?nameoflabel (used instead of 123) with l_nameoflabel for (Static varname = ?nameoflabel):

Code: Select all

s_Procname_v_varname dd l_nameoflabel
In that case it would work.
I think what you are needing is a feature request.
Which is why I posted this in a forum called "Feature Requests and Wishlists". :)

Posted: Fri Jun 12, 2009 10:34 pm
by Demivec
Trond wrote:When the compiler sees (Static varname = 123) it currently writes this to the near end of the asm file:

Code: Select all

s_Procname.v_varname dd 123
All that is needed to support this feature is to replace ?nameoflabel (used instead of 123) with l_nameoflabel for (Static varname = ?nameoflabel):

Code: Select all

s_Procname_v_varname dd l_nameoflabel
In that case it would work.
I think what you are needing is a feature request.
Which is why I posted this in a forum called "Feature Requests and Wishlists". :)
I agree. I think if this was implemented as you described it would take some of the rough edges off that are still present with using labels.

Regarding the comment on forums, I was distracted by the "I think this is a bug" part of your first post.

Posted: Fri Jun 12, 2009 10:55 pm
by Kaeru Gaman
I'm convinced by the argumentation. :D

should be possible to implement and would be a nice feature.