Currently a 'With..End With' block can support a temporary instance of a Type !

General FreeBASIC programming questions.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by fxm »

coderJeff wrote: Feb 19, 2023 16:35 explicit - constructor procedure written by user
implicit - constructor procedure generated by compiler
no constructor - inline assignments generated by compiler
  • We therefore agree with these definitions.

coderJeff wrote: Feb 19, 2023 16:35 However, throwing an error for "WITH TYPE<UDT>(...)" when no constructor exists seems like a simple way to manage something that doesn't work now and (is probably) hard to make work.
  • I agree that such temporary types (without any constructor) induce an error message when used with 'With'.

    So compared to the current functionality, there is just to add an error message for such temporary types (without any constructor).
    The other cases (instances with explicit or implicit constructor) already work.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by coderJeff »

Seems like not so simple. When 'TYPE<UDT>' has a constructor, the life time is correctly extended to the end of the WITH statement, even if used as an argument for function. But if there is no constructor, temporaries are immediately destroyed after the WITH statement.

Code: Select all

#define USE_CTOR 1

/'
if USE_CTOR 0
-- destructor is immediately called after WITH statement
Before WITH
~T()
 123
After END WITH

if USE_CTOR 1
-- life-time of variables (even temporaries) extended to end of WITH block
Before WITH
T()
 123
~T()
After END WITH
'/

type T
  a as short
  #if USE_CTOR 
    declare constructor( byval arg as short )
  #endif
  declare destructor()
end type

#if USE_CTOR
constructor T( byval arg as short )
  print "T()"
  a = arg
end constructor
#endif

destructor T()
	print "~T()"
end destructor

function f( byref x as T ) byref as T
  return x
end function

print "Before WITH"
with f(type<T>(123))
  print .a
end with
print "After END WITH"

sleep
The simple error message I was thinking of adding doesn't account for this example. I'll take another try at fixing the hard way.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by fxm »

Similar lack of compilation error for:

Code: Select all

dim byref as T ref = f(type<T>(123))
while the destruction is never postponed until the end of the scope, whatever USE_CTOR value.

('dim byref as T ref = type<T>(123)' is always forbidden, whatever USE_CTOR value)
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by coderJeff »

I thought a lot about this last week. Internally temporary types have a kind of default way of allocating the lifetime of the temporary instance and is not easy to override the default behaviour.

type<UDT>(...) is temporary instance
Important rules are:
- allocated to temporary variable
- destroyed after statement where it is used.

Exceptions:
- DIM = ... sometimes optimize the temporary instance away and just assign the initializer
- WITH statement (WIP)
- IIF(), don't instance the unused branch
- maybe SELECT CASE ?, I didn't test yet

But for now, I will just focus on WITH statement.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by coderJeff »

Updated in fbc/master, temporary types should work ok now in the WITH statement:

Code: Select all

with type<udt>(1,2, ...)
 ....
end with
For some other uses: passing temporary TYPEs as arguments to a function that returns it byref as a result- I don't see a way to automatically have the compiler figure out the lifetime of that instance. The caller and function don't know what the other is doing.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by fxm »

Thanks coderJeff.

But what about getting an error message for the following code (with or without a constructor)?

Code: Select all

#define USE_CTOR 1

type T
  a as short
  #if USE_CTOR 
    declare constructor( byval arg as short )
  #endif
  declare destructor()
end type

#if USE_CTOR
constructor T( byval arg as short )
  print "T()"
  a = arg
end constructor
#endif

destructor T()
	print "~T()"
end destructor

function f( byref x as T ) byref as T
  return x
end function

scope
  dim byref as T ref = f(type<T>(123))
  print "no error message while the reference is dangling"
end scope

sleep

Code: Select all

[ T() ]
~T()
no error message while the reference is dangling
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by coderJeff »

fxm wrote: Mar 04, 2023 14:31 But what about getting an error message for the following code (with or without a constructor)?
What I was kind of saying in my last post:

Passing temporary type to function not a problem on it's own, because function could be:

Code: Select all

function f( byref x as T ) byref as T
	static value as T = 0
	value = x
	return value
end function
scope
  '' this is OK because function returns a reference with longer lifetime than this scope
  dim byref as T ref = f(type<T>(123))
end scope
And in the function, returning an argument by reference not a problem on it's own, because caller could be:

Code: Select all

function f( byref x as T ) byref as T
  return x
end function
scope
  dim as T arg = type<T>(123)
  dim byref as T ref = f(arg)
  '' this is OK because ref is valid until end of scope
end scope
Only when we have the two together - passing a temporary type to a function that returns the argument as a byref result.
I don't know how we could detect that.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Currently a 'With..End With' block can support a temporary instance of a Type !

Post by fxm »

Documentation page updated:
- KeyPgWith → fxm [temporary types (without any constructor) are now supported]
Post Reply