Dim Byref syntax
Re: Dim Byref syntax
@Admin,
Have you seen my today comment on the "#842 BYREF (variable) does not report some assignment errors detectable on its internal pointer" bug report, which you just have to close ?
Have you seen my today comment on the "#842 BYREF (variable) does not report some assignment errors detectable on its internal pointer" bug report, which you just have to close ?
Re: Dim Byref syntax
In both cases, even though we start with `I as Const Integer`, the pointer types are explicitly being manipulated with a CAST, so keep that in mind.
CASE 1: Pointer details are hidden. I is CONST integer, but, CAST will cast away the CONST-ness, * operator will dereference, and because it is a BYREF variable, the address is implicitly taken and assigned. Result: No error.
CASE 2: Pointer details are exposed. I is CONST integer, but, CAST will cast away the CONST-ness, and the type conversion is not solved out. It's not a constant and can't be an initializer. Result: Error.
Code: Select all
Static As Const Integer I = 123
'' CASE 1, with BYREF: no error
Static Byref As Integer RI = *Cast(Integer Ptr, @I)
Print RI
'' CASE 2, with POINTER, error
Static As Integer Ptr pI = Cast(Integer Ptr, @I)
Print *pI
CASE 2: Pointer details are exposed. I is CONST integer, but, CAST will cast away the CONST-ness, and the type conversion is not solved out. It's not a constant and can't be an initializer. Result: Error.
Re: Dim Byref syntax
I know, not quite the same, but this should work with next pull request https://github.com/freebasic/fbc/pull/89fxm wrote:More simply/generally, the following code is not allowed:Code: Select all
Static As Integer I = 0 Static As Integer J = I
Code: Select all
dim shared a as integer = 5
dim shared byref b as integer = a
static byref As integer c = b
dim byref d as integer = c
print a, hex( @a )
print b, hex( @b )
print c, hex( @c )
print d, hex( @d )
Re: Dim Byref syntax
I closed it because I thought primary bug was fixed, no more segfaults.fxm wrote:@Admin,
Have you seen my today comment on the "#842 BYREF (variable) does not report some assignment errors detectable on its internal pointer" bug report, which you just have to close ?
I expanded one of the tests you wrote in this forum.
Code: Select all
type X extends OBJECT
static as const integer y
static as integer z
end type
dim as const integer X.y = 123
dim as integer X.z = 456
function cbv1() byref as const integer static
var byref u = X.y
return u
end function
function cbp1() byref as const integer static
var byref u = *cast(integer ptr, @X.y)
return u
end function
function cbp2() byref as const integer static
var byref u = *cast(const integer ptr, @X.y)
return u
end function
function cbp3() byref as const integer static
var byref u = *cast(integer const ptr, @X.y)
return u
end function
function cbp4() byref as const integer static
var byref u = *cast(const integer const ptr, @X.y)
return u
end function
function cpp1() byref as const integer static
var pu = cast(integer ptr, @X.y)
return *pu
end function
function cpp2() byref as const integer static
var pu = cast(const integer ptr, @X.y)
return *pu
end function
function cpp3() byref as const integer static
var pu = cast(integer const ptr, @X.y)
return *pu
end function
function cpp4() byref as const integer static
var pu = cast(const integer const ptr, @X.y)
return *pu
end function
function bv1() byref as const integer static
var byref u = X.z
return u
end function
function bp1() byref as const integer static
var byref u = *cast(integer ptr, @X.z)
return u
end function
function bp2() byref as const integer static
var byref u = *cast(const integer ptr, @X.z)
return u
end function
function bp3() byref as const integer static
var byref u = *cast(integer const ptr, @X.z)
return u
end function
function bp4() byref as const integer static
var byref u = *cast(const integer const ptr, @X.z)
return u
end function
function pp1() byref as const integer static
var pu = cast(integer ptr, @X.z)
return *pu
end function
function pp2() byref as const integer static
var pu = cast(const integer ptr, @X.z)
return *pu
end function
function pp3() byref as const integer static
var pu = cast(integer const ptr, @X.z)
return *pu
end function
function pp4() byref as const integer static
var pu = cast(const integer const ptr, @X.z)
return *pu
end function
? cbv1()
? cbp1(), cbp2(), cbp3(), cbp4()
? cpp1(), cpp2(), cpp3(), cpp4()
? bv1()
? bp1(), bp2(), bp3(), bp4()
? pp1(), pp2(), pp3(), pp4()
There could be multiple bugs here. I don't know. Currently BYREF succeeds where POINTER versions do not, except in -exx, they are both same.
Re: Dim Byref syntax
Since last post in this topic on Jun 22, I have been working on bugs related to the closed #842, which kind of started it all. My efforts are currently in pull request 90.
I've made my way through the following:
#642 Pointer casting allows constness dropping
#886 Inconsistent error with BYREF and CAST on CONST variables
#801 parser allows more constructs under -exx than without it
#727 RTL functions not checking Constness unless marked RTL_CONST
#880 Overload binary operators do not support covariant arguments
Currently testing overload resolution. I posted here because of the indirect relation to this thread and they are all related to each other. Plus the discussions are somewhat fragmented. If anyone knows of discussions that are related to any of these bugs, please update the sf.net ticket, and I could continue discussion in the individual forum topics.
I've made my way through the following:
#642 Pointer casting allows constness dropping
#886 Inconsistent error with BYREF and CAST on CONST variables
#801 parser allows more constructs under -exx than without it
#727 RTL functions not checking Constness unless marked RTL_CONST
#880 Overload binary operators do not support covariant arguments
Currently testing overload resolution. I posted here because of the indirect relation to this thread and they are all related to each other. Plus the discussions are somewhat fragmented. If anyone knows of discussions that are related to any of these bugs, please update the sf.net ticket, and I could continue discussion in the individual forum topics.
Re: Dim Byref syntax
Should it possible to return a null reference without resorting to an explicit cast overload (if that is possible):
Code: Select all
type tt extends object
s as string
end type
function NewTT(s as string) as tt
dim res as tt
if len(s) then
res.s = s
return res
end if
return *cptr(tt ptr, 0)
end function
dim t as tt
t = NewTT("hello")
if t <> 0 then ' not possible and member access raises segmetation fault
print "assigned"
else
print "nil"
end if
Re: Dim Byref syntax
I don't think that you can do that without using pointers explicitly. I would even have expected the application to crash when you "return *cptr(tt ptr, 0)", because you're returning an object. And this object is constructed from the dereferenced null reference, which should call the copy constructor of "tt". Maybe you're just lucky or maybe it's fine, I can't tell (at least not without deeper investigation). But I'd not use such code, but simply use pointers instead.
//edit: Wikipedia (https://en.wikipedia.org/wiki/Reference_(C%2B%2B)) says the following about references in C++ (and it's probably the same in FB):
//edit: Wikipedia (https://en.wikipedia.org/wiki/Reference_(C%2B%2B)) says the following about references in C++ (and it's probably the same in FB):
So it's an error no matter whether you return the object by value or as a reference, because you're dereferencing a null pointer either way.Wikipedia wrote:A reference shall be initialized to refer to a valid object or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the "object" obtained by dereferencing a null pointer, which causes undefined behavior. [...] ]
Re: Dim Byref syntax
Indeed in this case, using a reference is more complex than directly a pointer:
Code: Select all
type tt extends object
s as string
end type
function NewTT(byref s as string) byref as tt
if len(s) then
dim byref as tt res = *new tt
res.s = s
return res
end if
return *cptr(tt ptr, 0)
end function
dim byref as tt t = *cptr(tt ptr, 0)
@t = @(NewTT("hello"))
if @t <> 0 then
print "assigned"
else
print "nil"
end if
delete @t
@t = @(NewTT(""))
if @t <> 0 then
print "assigned"
else
print "nil"
end if
delete @t
sleep
Re: Dim Byref syntax
St_W wrote:I would even have expected the application to crash when you "return *cptr(tt ptr, 0)"
andfxm wrote:Presently, a reference can also be re-initialized to refer to nothing, a "null" reference (@ref = 0), and this can be done even at the level of its declaration
It's just that I prefer to use references as much as possible for my project, which should have easy access by default for novice programmers.fxm wrote: Presently one can also pass/return to/from a procedure a "null" reference by using '*Cptr(datatype Ptr, 0)', or even the short-cut syntax 'Byval 0'.
Re: Dim Byref syntax
Thanks for the example fxm, I was wrong evidently.
I had a look at the C code generated by the C emitter of FB for both return *cptr(tt ptr, 0) (with a byref return value) and dim byref as tt t = *cptr(tt ptr, 0). The generated code assigns the null pointer to the reference and does not try to dereference a null value (like if you had not declared it as byref). So the generated application is valid, despite the syntax suggesting otherwise.
Just as a (non-FB) sidenote: I recently read that the upcoming C# 8.0 release includes a new optional feature that will require to mark references as nullable if you want to assign null values to them (previously that was possible without any warnings). IMHO that's a nice solution for avoiding errors on one side and still allowing null references on the other side. If you're interested, here's the article: https://blogs.msdn.microsoft.com/dotnet ... ing-c-8-0/
//edit: Also note that you need to be extremely careful so that you do not dereference the null reference by accident. For example the copy constructor is called when you'd just write t = NewTT("") instead of @t = @(NewTT("")) in fxm's example. So I'd still suggest to use pointers explicitly if you need to deal with null references.
I had a look at the C code generated by the C emitter of FB for both return *cptr(tt ptr, 0) (with a byref return value) and dim byref as tt t = *cptr(tt ptr, 0). The generated code assigns the null pointer to the reference and does not try to dereference a null value (like if you had not declared it as byref). So the generated application is valid, despite the syntax suggesting otherwise.
Just as a (non-FB) sidenote: I recently read that the upcoming C# 8.0 release includes a new optional feature that will require to mark references as nullable if you want to assign null values to them (previously that was possible without any warnings). IMHO that's a nice solution for avoiding errors on one side and still allowing null references on the other side. If you're interested, here's the article: https://blogs.msdn.microsoft.com/dotnet ... ing-c-8-0/
//edit: Also note that you need to be extremely careful so that you do not dereference the null reference by accident. For example the copy constructor is called when you'd just write t = NewTT("") instead of @t = @(NewTT("")) in fxm's example. So I'd still suggest to use pointers explicitly if you need to deal with null references.
Re: Dim Byref syntax
The implementation of a nil object would be great, something like:
Code: Select all
dim t as tt ' type declared but no instance yet
t = new tt() ' new instance
' or
t = FuncTT()
Re: Dim Byref syntax
In a previous post, I proposed to authorize the syntax declaration of reference without initializer (for defining a null reference):
Dim Byref t As tt
equivalent to:
Dim Byref t As tt = *Cptr(tt Ptr, 0)
In all case, a reference can be reinitialized to point on an other object by:
@t = @object
(in particular, '@t = 0' allows to retrieve a null reference)
Dim Byref t As tt
equivalent to:
Dim Byref t As tt = *Cptr(tt Ptr, 0)
In all case, a reference can be reinitialized to point on an other object by:
@t = @object
(in particular, '@t = 0' allows to retrieve a null reference)
Re: Dim Byref syntax
Yes, that would be something. I generally don't like the immediate creation of the object of which a different copy would have to be made later on.fxm wrote:In a previous post, I proposed to authorize the syntax declaration of reference without initializer (for defining a null reference):
Dim Byref t As tt
equivalent to:
Dim Byref t As tt = *Cptr(tt Ptr, 0)
Re: Dim Byref syntax
Currently perhaps some obfuscation might be achieved:
Code: Select all
#define init(o) *cptr(o ptr, 0)
#define nil(o) @(o) = 0
type tt extends object
s as string
end type
function NewTT(s as string) byref as tt
if len(s) then
dim byref res as tt = *new tt()
res.s = s
return res
end if
return *cptr(tt ptr, 0)
end function
dim byref t as tt = init(tt)
@t = @(NewTT(""))
if not nil(t) then
print t.s
delete @t
else
print "no ref"
end if
Last edited by Munair on Nov 26, 2018 16:10, edited 1 time in total.
Re: Dim Byref syntax
Or, to make it really fancy:It might be over the top, but it shows in a clear manner what is happening.
Code: Select all
#define Init(o) *cptr(o ptr, 0)
#define Nil(o) @(o) = 0
#define Obj(o) byref o
#define Ref(o) @(o)
type tt extends object
s as string
end type
function NewTT(s as string) byref as tt
if len(s) then
dim Obj(res) as tt = *new tt()
res.s = s
return res
end if
return Init(tt)
end function
dim Obj(t) as tt = Init(tt)
Ref(t) = Ref(NewTT(""))
if not Nil(t) then
print t.s
delete Ref(t)
else
print "no ref"
end if
Last edited by Munair on Nov 26, 2018 16:23, edited 2 times in total.