Skip to content

Commit

Permalink
fbc: add PROCPTR( UDT.member [, signature] )
Browse files Browse the repository at this point in the history
- add PROCPTR( UDT.member [, SUB|FUNCTION ...] ) to get a procedure
  pointer for type member procedures
- PROCPTR( UDT.member ) will get the procedure pointer for the first declared
  member sub, function, constructor, destructor, operator, or property
- PROCPTR( UDT.member, signature ) will get the procedure pointer for
  the member matching the signature

  For example:
	type T
		as single number
		declare operator cast() as string
		declare operator cast() as integer
	end type

	operator T.cast() as string
		return str( number )
	end operator

	operator T.cast() as integer
		return int( number )
	end operator

	dim a as T = (4.5)

	var tostring = procptr( T.cast )
	var tointeger = procptr( T.cast, function() as integer )

	print tostring( a )  '' call method through pointer to member
	print tointeger( a ) '' call method through pointer to member

- regardless of the kind of member procedure, the signature must be written
  as a form of SUB(...) or FUNC(...) AS return_type.
- the instance parameter need not be specified since it will be implied from
  the member.
- PROCPTR( UDT.<property>, function(...) ... ) returns a pointer to the get
  method
- PROCPTR( UDT.<property>, sub(...) ) returns a pointer to the set method
  method
  • Loading branch information
jayrm committed Apr 4, 2023
1 parent 16062f6 commit 111553a
Show file tree
Hide file tree
Showing 3 changed files with 811 additions and 21 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Expand Up @@ -67,6 +67,7 @@ Version 1.10.0
- Add makefile option DISABLE_STDCXX_PATH to disable usnig gcc to search for some c++ library path
- fbc: allow typename.member symbol checks for #ifdef / #ifndef / defined() where member can be a data field, static data field, nested type, constructor, destructor, property, operator (self-assignment, new, new[], delete, delete[], let, cast, for, step, next), or member procedure.
- rtlib: dos: add "__fb_dos_no_dpmi_yield" variable to control calling "__dpmi_yield()" and prevent a crash under some dos extenders in dosbox
- fbc: PROCPTR( UDT.member [, SUB|FUNCTION ...] ) to get a procedure pointer for type member procedures

[fixed]
- gas64: missing restoring of use of one virtual register on sqr for float (SARG)
Expand Down
69 changes: 48 additions & 21 deletions src/compiler/parser-expr-unary.bas
Expand Up @@ -444,15 +444,45 @@ function cDerefExpression( ) as ASTNODE ptr
function = astBuildMultiDeref( derefcnt, expr, astGetFullType( expr ), astGetSubType( expr ) )
end function

private function hProcPtrResolveOverload _
( _
byval ovl_head_proc as FBSYMBOL ptr, _
byval proc as FBSYMBOL ptr, _
byval check_exact as boolean = FALSE _
) as FBSYMBOL ptr

dim as FBSYMBOL ptr sym = ovl_head_proc

if( symbIsOperator( ovl_head_proc ) ) then
dim as AST_OP op = any
op = symbGetProcOpOvl( ovl_head_proc )
sym = symbFindOpOvlProc( op, ovl_head_proc, proc )

elseif( symbIsProc( proc ) ) then
dim findopts as FB_SYMBFINDOPT = FB_SYMBFINDOPT_NONE

'' if it is a property then let the function pointer decide
'' if we are looking for the set or get procedure where
'' get is expected to have a return type
if( symbIsProperty( ovl_head_proc ) ) then
if( symbGetType( proc ) <> FB_DATATYPE_VOID ) then
findopts = FB_SYMBFINDOPT_PROPGET
end if
end if
sym = symbFindOverloadProc( ovl_head_proc, proc, findopts )

end if

return sym
end function

private function hProcPtrBody _
( _
byval base_parent as FBSYMBOL ptr, _
byval proc as FBSYMBOL ptr, _
byval check_exact as boolean = FALSE _
) as ASTNODE ptr

dim as FBSYMBOL ptr sym = any

'' '('')'?
if( lexGetToken( ) = CHAR_LPRNT ) then
lexSkipToken( )
Expand All @@ -463,24 +493,19 @@ private function hProcPtrBody _
end if

'' resolve overloaded procs
if( (symbIsOverloaded( proc ) <> 0) or (check_exact <> FALSE) ) then
if( parser.ctxsym <> NULL ) then
if( symbIsProc( parser.ctxsym ) ) then
sym = symbFindOverloadProc( proc, parser.ctxsym )
if( sym <> NULL ) then
proc = sym
elseif( check_exact ) then
errReport( FB_ERRMSG_NOMATCHINGPROC, TRUE )
return astNewCONSTi( 0 )
end if
if( parser.ctxsym <> NULL ) then
if( symbIsOverloaded( proc ) or check_exact ) then
dim as FBSYMBOL ptr sym = any
sym = hProcPtrResolveOverload( proc, parser.ctxsym )

if( sym ) then
proc = sym
elseif( check_exact ) then
errReport( FB_ERRMSG_NOMATCHINGPROC, TRUE )
return astNewCONSTi( 0 )
end if
end if
end if

'' taking the address of an method? pointer to methods not supported yet..
if( symbIsMethod( proc ) ) then
errReportEx( FB_ERRMSG_ACCESSTONONSTATICMEMBER, symbGetFullProcName( proc ) )
return astNewCONSTi( 0 )
end if

'' Check visibility of the proc
Expand Down Expand Up @@ -642,15 +667,17 @@ function cAddrOfExpression( ) as ASTNODE ptr
dim as FBSYMBOL ptr sym = any, base_parent = any

chain_ = cIdentifier( base_parent, _
FB_IDOPT_DEFAULT or FB_IDOPT_ALLOWSTRUCT )
sym = symbFindByClass( chain_, FB_SYMBCLASS_PROC )
FB_IDOPT_CHECKSTATIC or _
FB_IDOPT_ALLOWSTRUCT or _
FB_IDOPT_ALLOWOPERATOR )

sym = cIdentifierIfDefined( base_parent, chain_ )

if( sym = NULL ) then
errReport( FB_ERRMSG_UNDEFINEDSYMBOL )
'' error recovery: skip until ')' and fake a node
hSkipUntil( CHAR_RPRNT, TRUE )
return astNewCONSTi( 0 )
else
lexSkipToken( LEXCHECK_POST_LANG_SUFFIX )
end if

'' ',' ?
Expand Down

0 comments on commit 111553a

Please sign in to comment.