Skip to content

Commit 3437197

Browse files
committed
fbc: sf.net #666: allow overload 'as string' with 'as zstring ptr' parameters
- previously fbc was unable to overload various [w|z]string-type [ptr] parameters since fbc grouped all strings as one type with implicit conversions - this update allows overloading string-type parameters and improves overload resolution to avoid ambiguous conversions - string conversions are ranked in a similar way as integer conversions where conversions to a particular string type will be preferred to conversions to some other string-type - possibly we will see some new const qualifier / overloading bugs, to be dealt with later
1 parent 0f1ff15 commit 3437197

File tree

6 files changed

+158
-67
lines changed

6 files changed

+158
-67
lines changed

changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Version 1.09.0
1313
- fbc: gen gcc: allow compiling with GCC 4.5 and older, by avoiding -Wno-unused-but-set-variable (TeeEmCee)
1414
- fbc: internal function fbcQueryGcc() to ask gcc for the correct as & ld to use (TeeEmCee)
1515
- rtlib: freebsd: minimum thread stacksize 8192 KiB
16+
- sf.net #666: allow overload 'as string' with 'as zstring ptr' parameters
1617

1718
[added]
1819
- fbc: add '-z fbrt' command line option to link against libfbrt*.a instead of libfb*.a
@@ -23,6 +24,7 @@ Version 1.09.0
2324
- fbc: add '-entry name' command line option to set program entry point (TeeEmCee)
2425
- added objinfo support for ELF files on freebsd
2526
- PROCPTR( identifier, type ) syntax to allow getting procedure pointer for based on sub/function type
27+
- sf.net #666: overload matching for UDT's with CAST() operators as [w|z]string type and implicit conversions
2628

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

src/compiler/symb-data.bas

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ sub symbDataInit( )
134134
'' populate symb_dtypeMatchTB() with ranking numbers
135135
for i = 0 to NUMTYPES - 1
136136
dtype2 = rank(i)
137-
symb_dtypeMatchTB( dtype1, dtype2 ) = i * FB_OVLPROC_CONVSCALE
137+
symb_dtypeMatchTB( dtype1, dtype2 ) = OvlMatchScore( i, 0 )
138138
next
139139

140140
next
@@ -525,15 +525,20 @@ end function
525525
'' result:
526526
''
527527
'' FB_OVLPROC_FULLMATCH => compatible, exact match
528+
'' FB_OVLPROC_FULLMATCH - stringrank => compatible, distance between string types (no w<->z conversion)
528529
'' FB_OVLPROC_FULLMATCH - baselevel => compatible, derived types
529530
'' FB_OVLPROC_TYPEMATCH + consts => same type, different consts
530531
'' FB_OVLPROC_HALFMATCH => compatible, same data type class
531532
'' FB_OVLPROC_HALFMATCH - rank => compatible, distance between numeric types
532-
'' FB_OVLPROC_HALFMATCH - struct => compatible, UDT ctor/cast
533+
'' FB_OVLPROC_HALFMATCH - stringrank => compatible, distance between string types (w<->z conversion)
534+
'' FB_OVLPROC_CONVMATCH - struct => compatible, UDT ctor
535+
'' FB_OVLPROC_CASTMATCH => compatible, implicit cast required (udt and string casts)
536+
'' FB_OVLPROC_CONVMATCH => compatible, implicit conversion required (udt and string conversions)
537+
'' FB_OVLPROC_CONVMATCH - struct => compatible, lowest UDT conv/cast
533538
'' FB_OVLPROC_LOWEST_MATCH => compatible, lowest scoring parameter
534539
'' FB_OVLPROC_NO_MATCH => incompatible
535540

536-
'' FB_OVLPROC_CONVSCALE => granularity of the matching score
541+
'' FB_OVLPROC_MAJORSCALE => granularity of the matching score
537542

538543
''
539544
function typeCalcMatch _
@@ -560,7 +565,7 @@ function typeCalcMatch _
560565
end if
561566

562567
if( (typeGetDtAndPtrOnly( ldtype ) = typeGetDtAndPtrOnly( rdtype )) and (lsubtype = rsubtype) ) then
563-
return FB_OVLPROC_TYPEMATCH + const_matches * FB_OVLPROC_CONVSCALE
568+
return FB_OVLPROC_TYPEMATCH + OvlMatchScore( const_matches, 0 )
564569
end if
565570

566571
'' We know that they're different (in terms of dtype or subtype or both),

src/compiler/symb-proc.bas

Lines changed: 80 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -542,22 +542,7 @@ private function hAddOvlProc _
542542

543543
'' not the same type? check next proc..
544544
if( pdtype <> odtype ) then
545-
546-
'' handle special cases: zstring ptr and string args
547-
select case pdtype
548-
case typeAddrOf( FB_DATATYPE_CHAR )
549-
if( odtype <> FB_DATATYPE_STRING ) then
550-
exit do
551-
end if
552-
553-
case FB_DATATYPE_STRING
554-
if( odtype <> typeAddrOf( FB_DATATYPE_CHAR ) ) then
555-
exit do
556-
end if
557-
558-
case else
559-
exit do
560-
end select
545+
exit do
561546
end if
562547

563548
if( param->subtype <> ovl_param->subtype ) then
@@ -1639,14 +1624,15 @@ end function
16391624
rec_cnt -= 1
16401625

16411626
if( proc <> NULL ) then
1642-
return FB_OVLPROC_HALFMATCH - FB_DATATYPE_STRUCT * FB_OVLPROC_CONVSCALE
1627+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( FB_DATATYPE_STRUCT, 0 )
16431628
end if
16441629
end if
16451630
#endmacro
16461631

16471632
#macro hCheckCastOvlEx _
16481633
( _
16491634
rec_cnt, _
1635+
param_mode, _
16501636
param_dtype, _
16511637
param_subtype, _
16521638
arg_expr _
@@ -1658,22 +1644,36 @@ end function
16581644

16591645
rec_cnt += 1
16601646
proc = symbFindCastOvlProc( param_dtype, _
1661-
param_subtype, _
1662-
arg_expr, _
1663-
@err_num )
1664-
rec_cnt -= 1
1647+
param_subtype, _
1648+
arg_expr, _
1649+
@err_num )
1650+
rec_cnt -= 1
16651651

16661652
if( proc <> NULL ) then
16671653
'' calculate a new match score based on the CAST() return type rank
1668-
var match = typeCalcMatch( param_dtype, param_subtype, symbGetParamMode( param ), symbGetFullType( proc ), symbGetSubType( proc ) )
1654+
'' we can't keep the FB_OVLPROC_TYPEMATCH and FB_OVLPROC_HALFMATCH
1655+
'' level of match scores because we don't wnat the score to interfere
1656+
'' with non-cast and non-conversion scores. Instead, reduce the scores:
1657+
'' FB_OVLPROC_TYPEMATCH => FB_OVLPROC_CASTMATCH
1658+
'' FB_OVLPROC_HALFMATCH => FB_OVLPROC_CONVMATCH
1659+
1660+
var match = hCalcTypesDiff( param_dtype, _
1661+
param_subtype, _
1662+
symbGetPtrCnt( proc ), _
1663+
symbGetFullType( proc ), _
1664+
symbGetSubType( proc ), _
1665+
NULL, _
1666+
param_mode )
16691667

16701668
if( match >= FB_OVLPROC_TYPEMATCH ) then
1671-
return FB_OVLPROC_HALFMATCH - FB_DATATYPE_STRUCT * FB_OVLPROC_CONVSCALE + 2
1669+
match = match - FB_OVLPROC_TYPEMATCH + FB_OVLPROC_CASTMATCH
16721670
elseif( match >= FB_OVLPROC_HALFMATCH ) then
1673-
return FB_OVLPROC_HALFMATCH - FB_DATATYPE_STRUCT * FB_OVLPROC_CONVSCALE + 1
1671+
match = match - FB_OVLPROC_TYPEMATCH + FB_OVLPROC_CONVMATCH
1672+
else
1673+
match = FB_OVLPROC_CONVMATCH - OvlMatchScore( FB_DATATYPE_STRUCT, 0 )
16741674
end if
16751675

1676-
return FB_OVLPROC_HALFMATCH - FB_DATATYPE_STRUCT * FB_OVLPROC_CONVSCALE
1676+
return match
16771677
end if
16781678
end if
16791679
#endmacro
@@ -1702,6 +1702,17 @@ private function hCalcTypesDiff _
17021702

17031703
arg_dclass = typeGetClass( arg_dtype )
17041704

1705+
'' STRING MATCHING
1706+
'' (F=FB_OVLPROC_FULLMATCH, H=FB_OVLPROC_HALFMATCH)
1707+
''
1708+
'' from / to -> string zstring zstring ptr wstring wstring ptr
1709+
'' ------------ ----------- ----------- ----------- ----------- -----------
1710+
'' string F-0 F-1 F-2 H-3 H-4
1711+
'' zstring F-2 F-0 F-1 H-3 H-4
1712+
'' zstring ptr F-2 F-1 F-0 H-3 H-4
1713+
'' wstring H-2 H-3 H-4 F-0 F-1
1714+
'' wstring ptr H-2 H-3 H-4 F-1 F-0
1715+
17051716
'' check classes
17061717
select case as const typeGetClass( param_dtype )
17071718
'' integer?
@@ -1720,17 +1731,21 @@ private function hCalcTypesDiff _
17201731
case FB_DATATYPE_CHAR
17211732
select case( arg_dtype )
17221733
case FB_DATATYPE_CHAR
1723-
return FB_OVLPROC_FULLMATCH
1734+
'' zstring => zstring
1735+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 0 )
17241736
case FB_DATATYPE_WCHAR
1725-
return FB_OVLPROC_HALFMATCH
1737+
'' wstring => zstring
1738+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 3 )
17261739
end select
17271740
return FB_OVLPROC_NO_MATCH
17281741
case FB_DATATYPE_WCHAR
17291742
select case( arg_dtype )
17301743
case FB_DATATYPE_CHAR
1731-
return FB_OVLPROC_HALFMATCH
1744+
'' zstring => wstring
1745+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 3 )
17321746
case FB_DATATYPE_WCHAR
1733-
return FB_OVLPROC_FULLMATCH
1747+
'' wstring => wstring
1748+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 0 )
17341749
end select
17351750
return FB_OVLPROC_NO_MATCH
17361751

@@ -1741,16 +1756,20 @@ private function hCalcTypesDiff _
17411756
case typeAddrOf( FB_DATATYPE_CHAR )
17421757
select case( arg_dtype )
17431758
case FB_DATATYPE_CHAR
1744-
return FB_OVLPROC_FULLMATCH
1759+
'' zstring => zstring ptr
1760+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 1 )
17451761
case FB_DATATYPE_WCHAR
1746-
return FB_OVLPROC_HALFMATCH
1762+
'' wstring => zstring ptr
1763+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 4 )
17471764
end select
17481765
case typeAddrOf( FB_DATATYPE_WCHAR )
17491766
select case( arg_dtype )
17501767
case FB_DATATYPE_CHAR
1751-
return FB_OVLPROC_HALFMATCH
1768+
'' zstring => wstring ptr
1769+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 4 )
17521770
case FB_DATATYPE_WCHAR
1753-
return FB_OVLPROC_FULLMATCH
1771+
'' wstring => wstring ptr
1772+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 1 )
17541773
end select
17551774

17561775
'' Any other non-z/wstring param from FB_DATACLASS_INTEGER:
@@ -1831,13 +1850,17 @@ private function hCalcTypesDiff _
18311850
case FB_DATACLASS_STRING
18321851
select case param_dtype
18331852
case FB_DATATYPE_CHAR
1834-
return FB_OVLPROC_FULLMATCH
1853+
'' string => zstring
1854+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 1 )
18351855
case typeAddrOf( FB_DATATYPE_CHAR )
1836-
return FB_OVLPROC_FULLMATCH
1856+
'' string => zstring ptr
1857+
return FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 2 )
18371858
case FB_DATATYPE_WCHAR
1838-
return FB_OVLPROC_HALFMATCH
1859+
'' string => wstring
1860+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 3 )
18391861
case typeAddrOf( FB_DATATYPE_WCHAR )
1840-
return FB_OVLPROC_HALFMATCH
1862+
'' string => wstring ptr
1863+
return FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 4 )
18411864
end select
18421865

18431866
end select
@@ -1878,9 +1901,11 @@ private function hCalcTypesDiff _
18781901
case FB_DATACLASS_INTEGER
18791902
select case arg_dtype
18801903
case FB_DATATYPE_CHAR
1881-
function = FB_OVLPROC_FULLMATCH
1904+
'' zstring => string
1905+
function = FB_OVLPROC_FULLMATCH - OvlMatchScore( 0, 2 )
18821906
case FB_DATATYPE_WCHAR
1883-
function = FB_OVLPROC_HALFMATCH
1907+
'' wstring => string
1908+
function = FB_OVLPROC_HALFMATCH - OvlMatchScore( 0, 2 )
18841909
end select
18851910

18861911
end select
@@ -1993,7 +2018,7 @@ private function hCheckOvlParam _
19932018
case FB_DATATYPE_STRUCT
19942019
var baselevel = symbGetUDTBaseLevel( arg_subtype, param_subtype )
19952020
if( baselevel > 0 ) then
1996-
match = FB_OVLPROC_FULLMATCH - baselevel
2021+
match = FB_OVLPROC_FULLMATCH - OvlMatchScore( baselevel, 0 )
19972022
end if
19982023
case FB_DATATYPE_FUNCTION
19992024
match = symbCalcProcMatch( param_subtype, arg_subtype, 0 )
@@ -2015,9 +2040,9 @@ private function hCheckOvlParam _
20152040
'' They're compatible despite having different CONSTs -- e.g. "non-const Foo" passed to "Byref As Const Foo".
20162041
'' Treat it as lower score match than an exact match.
20172042
if( match > FB_OVLPROC_TYPEMATCH ) then
2018-
match -= FB_DATATYPES
2043+
match -= OvlMatchScore( FB_DATATYPES, 0 )
20192044
end if
2020-
match += const_matches
2045+
match += OvlMatchScore( const_matches, 0 )
20212046
return match
20222047
end if
20232048

@@ -2034,7 +2059,7 @@ private function hCheckOvlParam _
20342059
hCheckCtorOvl( ctor_rec_cnt, param_subtype, arg_expr, arg_mode )
20352060

20362061
'' and at last, try implicit casting..
2037-
hCheckCastOvlEx( cast_rec_cnt, param_dtype, param_subtype, arg_expr )
2062+
hCheckCastOvlEx( cast_rec_cnt, symbGetParamMode( param ), param_dtype, param_subtype, arg_expr )
20382063
return FB_OVLPROC_NO_MATCH
20392064

20402065
'' enum param? refuse any other argument type, even integers,
@@ -2046,19 +2071,19 @@ private function hCheckOvlParam _
20462071
select case arg_dtype
20472072
'' UDT arg? try implicit casting..
20482073
case FB_DATATYPE_STRUCT ', FB_DATATYPE_CLASS
2049-
hCheckCastOvlEx( cast_rec_cnt, symbGetFullType( param ), param_subtype, arg_expr )
2074+
hCheckCastOvlEx( cast_rec_cnt, symbGetParamMode( param ), symbGetFullType( param ), param_subtype, arg_expr )
20502075
return FB_OVLPROC_NO_MATCH
20512076
end select
20522077
end select
20532078

20542079
'' last resource, calc the differences
20552080
function = hCalcTypesDiff( symbGetFullType( param ), _
2056-
param_subtype, _
2057-
param_ptrcnt, _
2058-
astGetFullType( arg_expr ), _
2059-
arg_subtype, _
2060-
arg_expr, _
2061-
symbGetParamMode( param ) )
2081+
param_subtype, _
2082+
param_ptrcnt, _
2083+
astGetFullType( arg_expr ), _
2084+
arg_subtype, _
2085+
arg_expr, _
2086+
symbGetParamMode( param ) )
20622087

20632088
end function
20642089

@@ -2461,11 +2486,11 @@ private function hCheckCastOvl _
24612486

24622487
'' last resource, calc the differences
24632488
function = hCalcTypesDiff( proc_dtype, _
2464-
proc_subtype, _
2465-
symbGetPtrCnt( proc ), _
2466-
to_dtype, _
2467-
to_subtype, _
2468-
NULL )
2489+
proc_subtype, _
2490+
symbGetPtrCnt( proc ), _
2491+
to_dtype, _
2492+
to_subtype, _
2493+
NULL )
24692494

24702495
end function
24712496

src/compiler/symb.bi

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,18 @@ const FB_DT_CONSTPOS = FB_DT_PTRPOS + 4
6969

7070
const FB_DT_MANGLEPOS = 20
7171

72+
const FB_OVLPROC_MINORSCALE = 10
73+
74+
#define OvlMatchScore(major, minor) (((major) * FB_OVLPROC_MINORSCALE) + (minor))
75+
7276
enum FB_OVLPROC_MATCH_SCORE
7377
FB_OVLPROC_NO_MATCH = 0
7478
FB_OVLPROC_LOWEST_MATCH = 1
75-
FB_OVLPROC_CONVSCALE = 2
76-
FB_OVLPROC_HALFMATCH = FB_DATATYPES * 1 * FB_OVLPROC_CONVSCALE
77-
FB_OVLPROC_TYPEMATCH = FB_DATATYPES * 2 * FB_OVLPROC_CONVSCALE
78-
FB_OVLPROC_FULLMATCH = FB_DATATYPES * 3 * FB_OVLPROC_CONVSCALE
79+
FB_OVLPROC_CONVMATCH = OvlMatchScore( FB_DATATYPES * 1, 0 )
80+
FB_OVLPROC_CASTMATCH = OvlMatchScore( FB_DATATYPES * 2, 0 )
81+
FB_OVLPROC_HALFMATCH = OvlMatchScore( FB_DATATYPES * 3, 0 )
82+
FB_OVLPROC_TYPEMATCH = OvlMatchScore( FB_DATATYPES * 4, 0 )
83+
FB_OVLPROC_FULLMATCH = OvlMatchScore( FB_DATATYPES * 5, 0 )
7984
end enum
8085

8186
enum

0 commit comments

Comments
 (0)