Skip to content

Commit 8539e1d

Browse files
authored
Merge pull request #331 from jayrm/procptr-type
fbc: add syntax for PROCPTR( identifier, type )
2 parents 86bac49 + bc070fd commit 8539e1d

File tree

4 files changed

+163
-3
lines changed

4 files changed

+163
-3
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Version 1.09.0
2222
- darwin: Implemented objinfo for Darwin/OSX Mach-O .o files, so #inclib etc. work (TeeEmCee)
2323
- fbc: add '-entry name' command line option to set program entry point (TeeEmCee)
2424
- added objinfo support for ELF files on freebsd
25+
- PROCPTR( identifier, type ) syntax to allow getting procedure pointer for based on sub/function type
2526

2627
[fixed]
2728
- github #315: set parameters when calling SCREENCONTROL (was broken in fbc 1.08.0 due to new LONG/LONGINT SCREENCONTROL API's)

src/compiler/parser-expr-unary.bas

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ end function
429429
private function hProcPtrBody _
430430
( _
431431
byval base_parent as FBSYMBOL ptr, _
432-
byval proc as FBSYMBOL ptr _
432+
byval proc as FBSYMBOL ptr, _
433+
byval check_exact as boolean = FALSE _
433434
) as ASTNODE ptr
434435

435436
dim as FBSYMBOL ptr sym = any
@@ -444,12 +445,15 @@ private function hProcPtrBody _
444445
end if
445446

446447
'' resolve overloaded procs
447-
if( symbIsOverloaded( proc ) ) then
448+
if( symbIsOverloaded( proc ) or check_exact ) then
448449
if( parser.ctxsym <> NULL ) then
449450
if( symbIsProc( parser.ctxsym ) ) then
450451
sym = symbFindOverloadProc( proc, parser.ctxsym )
451452
if( sym <> NULL ) then
452453
proc = sym
454+
elseif( check_exact ) then
455+
errReport( FB_ERRMSG_NOMATCHINGPROC, TRUE )
456+
return astNewCONSTi( 0 )
453457
end if
454458
end if
455459
end if
@@ -630,7 +634,35 @@ function cAddrOfExpression( ) as ASTNODE ptr
630634
lexSkipToken( LEXCHECK_POST_LANG_SUFFIX )
631635
end if
632636

633-
expr = hProcPtrBody( base_parent, sym )
637+
'' ',' ?
638+
if( hMatch( CHAR_COMMA ) ) then
639+
dim dtype as integer
640+
dim subtype as FBSYMBOL ptr
641+
if( cSymbolType( dtype, subtype ) = FALSE ) then
642+
errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
643+
'' error recovery: skip until ')' and fake a node
644+
hSkipUntil( CHAR_RPRNT, TRUE )
645+
return astNewCONSTi( 0 )
646+
else
647+
if( typeGetDtAndPtrOnly( dtype ) = typeAddrOf( FB_DATATYPE_FUNCTION ) ) then
648+
dim oldsym as FBSYMBOL ptr = parser.ctxsym
649+
dim old_dtype as integer = parser.ctx_dtype
650+
parser.ctxsym = subtype
651+
parser.ctx_dtype = dtype
652+
expr = hProcPtrBody( base_parent, sym, TRUE )
653+
parser.ctxsym = oldsym
654+
parser.ctx_dtype = old_dtype
655+
else
656+
errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
657+
'' error recovery: skip until ')' and fake a node
658+
hSkipUntil( CHAR_RPRNT, TRUE )
659+
return astNewCONSTi( 0 )
660+
end if
661+
end if
662+
663+
else
664+
expr = hProcPtrBody( base_parent, sym )
665+
end if
634666

635667
'' ')'
636668
if( hMatch( CHAR_RPRNT ) = FALSE ) then

tests/pointers/procptr-type.bas

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include "fbcunit.bi"
2+
3+
dim shared id as string
4+
5+
sub s overload ()
6+
id = "s()"
7+
end sub
8+
9+
sub s( byval arg as byte )
10+
id = "s( byval arg as byte )"
11+
end sub
12+
13+
sub s( byval arg as short )
14+
id = "s( byval arg as short )"
15+
end sub
16+
17+
sub s( byval arg as long )
18+
id = "s( byval arg as long )"
19+
end sub
20+
21+
sub s( byval arg as longint )
22+
id = "s( byval arg as longint )"
23+
end sub
24+
25+
sub s( byval arg as single )
26+
id = "s( byval arg as single )"
27+
end sub
28+
29+
sub s( byval arg as double )
30+
id = "s( byval arg as double )"
31+
end sub
32+
33+
34+
SUITE( fbc_tests.pointers.procptr_type )
35+
36+
TEST( subs )
37+
38+
scope
39+
var p1 = procptr(s)
40+
p1()
41+
CU_ASSERT( id = "s()" )
42+
end scope
43+
44+
scope
45+
var p1 = procptr(s, sub() )
46+
p1()
47+
CU_ASSERT( id = "s()" )
48+
end scope
49+
50+
scope
51+
var p1 = procptr(s, sub( byval as byte ) )
52+
p1(0)
53+
CU_ASSERT( id = "s( byval arg as byte )" )
54+
end scope
55+
56+
scope
57+
var p1 = procptr(s, sub( byval as short ) )
58+
p1(0)
59+
CU_ASSERT( id = "s( byval arg as short )" )
60+
end scope
61+
62+
scope
63+
var p1 = procptr(s, sub( byval as long ) )
64+
p1(0)
65+
CU_ASSERT( id = "s( byval arg as long )" )
66+
end scope
67+
68+
scope
69+
var p1 = procptr(s, sub( byval as longint ) )
70+
p1(0)
71+
CU_ASSERT( id = "s( byval arg as longint )" )
72+
end scope
73+
74+
scope
75+
var p1 = procptr(s, sub( byval as single ) )
76+
p1(0)
77+
CU_ASSERT( id = "s( byval arg as single )" )
78+
end scope
79+
80+
scope
81+
var p1 = procptr(s, sub( byval as double ) )
82+
p1(0)
83+
CU_ASSERT( id = "s( byval arg as double )" )
84+
end scope
85+
86+
END_TEST
87+
88+
TEST( types )
89+
90+
type t as sub( byval as single )
91+
92+
scope
93+
var p1 = procptr(s, sub( byval as single ) )
94+
p1(0)
95+
CU_ASSERT( id = "s( byval arg as single )" )
96+
end scope
97+
98+
scope
99+
var p1 = procptr(s, t )
100+
p1(0)
101+
CU_ASSERT( id = "s( byval arg as single )" )
102+
end scope
103+
104+
scope
105+
var p1 = procptr(s, typeof(t) )
106+
p1(0)
107+
CU_ASSERT( id = "s( byval arg as single )" )
108+
109+
var p2 = procptr(s, typeof(p1) )
110+
p2(0)
111+
CU_ASSERT( id = "s( byval arg as single )" )
112+
end scope
113+
114+
115+
END_TEST
116+
117+
END_SUITE

todo.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@ o -exx should catch...
269269
prototypes don't require a name and because overloading
270270
- := must be a new token because the "foo bar : baz" ambiguity
271271

272+
[ ] method pointers / delegates
273+
- extend PROCPTR( id, type ) to allow pointers to methods
274+
- fbc handles method pointers fairly well but the syntax is not symmetrical with
275+
invoking a method on a TYPE (class)
276+
- var x = procptr( T.method ) could return a method pointer but must currently be
277+
invoked with x( instance, [params]... ). This is a different syntax from other
278+
languages that support method pointers.
279+
- delegates would need to aggregate the instance and method pointer which will
280+
likely requre a new built-in type to handle by the compiler
281+
272282
*** *** *** *** ***
273283
[ ] All functions returning STRING should actually return the FBSTRING object
274284
- it must be coded in plain C to avoid C++ dependencies

0 commit comments

Comments
 (0)