Code: Select all
Union
Type Field = 2
As UShort t_BH
As UInteger t_A
As UShort t_BL
End Type
Type
...
Code: Select all
Union
Type Field = 2
As UShort t_BH
As UInteger t_A
As UShort t_BL
End Type
Type
...
Code: Select all
TYPE udt1 FIELD = 2
AS USHORT t_BH
AS UINTEGER t_A
AS USHORT t_BL
END TYPE
TYPE udt2
AS INTEGER i1, i2
END TYPE
UNION uni
AS udt1 u1
AS udt2 u2
END UNION
Code: Select all
Type SDS Field = 2
Union
Type
As UShort SD_BH
As UInteger SD_A
As UShort SD_BL
End Type
Type
As UInteger D_A
As UInteger D_B
End Type
..
Code: Select all
type T [field = N]
union
...
end union
end type
Code: Select all
union T [field = N]
...
end union
Code: Select all
diff --git a/changelog.txt b/changelog.txt
index 78809bc..dd2e6fc 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -27,6 +27,7 @@ Version 0.24.0:
- 'fbc -static' option to tell the linker to link against static libraries if installed
- CONST may now be specified in front of the bodies of CONST methods, not just in the declaration, same as for STATIC
- "Real" Rnd() algorithm (activate via 'Randomize(, 5)') using Win32 Crypto APIs or Linux /dev/urandom
+- FIELD = N can now be used on nested anonymous TYPEs/UNIONs
[fixed]
- Subtracting pointers from numbers, e.g. (i-p) was being allowed, rearranging to (p-i)
diff --git a/compiler/parser-decl-struct.bas b/compiler/parser-decl-struct.bas
index bff85fe..0ca0b5f 100644
--- a/compiler/parser-decl-struct.bas
+++ b/compiler/parser-decl-struct.bas
@@ -564,6 +564,49 @@ private function hTypeAdd _
end function
+'' [FIELD '=' ConstExpression]
+private function cFieldAlignmentAttribute( ) as integer
+ '' FIELD
+ if( lexGetToken( ) <> FB_TK_FIELD ) then
+ return 0
+ end if
+
+ lexSkipToken( )
+
+ '' '='
+ if( hMatch( FB_TK_ASSIGN ) = FALSE ) then
+ errReport( FB_ERRMSG_SYNTAXERROR )
+ end if
+
+ '' ConstExpression
+ dim as ASTNODE ptr expr = cExpression( )
+ if( expr = NULL ) then
+ errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
+ '' error recovery: fake an expr
+ expr = astNewCONSTi( 0, FB_DATATYPE_INTEGER )
+ end if
+
+ if( astIsCONST( expr ) = FALSE ) then
+ errReport( FB_ERRMSG_EXPECTEDCONST )
+ '' error recovery: fake an expr
+ astDelTree( expr )
+ expr = astNewCONSTi( 0, FB_DATATYPE_INTEGER )
+ end if
+
+ '' follow the GCC 3.x ABI
+ dim as integer align = astGetValueAsInt( expr )
+ astDelNode( expr )
+ if( align < 0 ) then
+ align = 0
+ elseif( align > FB_INTEGERSIZE ) then
+ align = 0
+ elseif( align = 3 ) then
+ align = 2
+ end if
+
+ return align
+end function
+
'':::::
''TypeBody = ( (UNION|TYPE Comment? SttSeparator
'' ElementDecl
@@ -638,7 +681,8 @@ private function hTypeBody _
case FB_TK_TYPE, FB_TK_UNION
'' isn't it a field called TYPE|UNION?
select case as const lexGetLookAhead( 1 )
- case FB_TK_EOL, FB_TK_EOF, FB_TK_COMMENT, FB_TK_REM
+ case FB_TK_EOL, FB_TK_EOF, FB_TK_COMMENT, FB_TK_REM, _
+ FB_TK_FIELD
decl_inner: '' it's an anonymous inner UDT
isunion = lexGetToken( ) = FB_TK_UNION
@@ -658,8 +702,14 @@ decl_inner: '' it's an anonymous inner UDT
lexSkipToken( )
+ '' [FIELD '=' ConstExpression]
+ dim as integer align = cFieldAlignmentAttribute( )
+ if( align = 0 ) then
+ align = symbGetUDTAlign( s )
+ end if
+
'' create a "temp" one
- inner = hTypeAdd( s, NULL, NULL, isunion, symbGetUDTAlign( s ) )
+ inner = hTypeAdd( s, NULL, NULL, isunion, align )
if( inner = NULL ) then
exit function
end if
@@ -786,11 +836,10 @@ function cTypeDecl _
byval attrib as FB_SYMBATTRIB _
) as integer
- static as zstring * FB_MAXNAMELEN+1 id
- dim as ASTNODE ptr expr = any
- dim as integer align, isunion, checkid = any
- dim as FBSYMBOL ptr sym = any
- dim as FB_CMPSTMTSTK ptr stk = any
+ static as zstring * FB_MAXNAMELEN+1 id
+ dim as integer isunion = any, checkid = any
+ dim as FBSYMBOL ptr sym = any
+ dim as FB_CMPSTMTSTK ptr stk = any
function = FALSE
@@ -875,42 +924,8 @@ function cTypeDecl _
end if
end if
- '' (FIELD '=' Expression)?
- if( lexGetToken( ) = FB_TK_FIELD ) then
- lexSkipToken( )
-
- if( hMatch( FB_TK_ASSIGN ) = FALSE ) then
- errReport( FB_ERRMSG_SYNTAXERROR )
- end if
-
- expr = cExpression( )
- if( expr = NULL ) then
- errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
- '' error recovery: fake an expr
- expr = astNewCONSTi( 0, FB_DATATYPE_INTEGER )
- end if
-
- if( astIsCONST( expr ) = FALSE ) then
- errReport( FB_ERRMSG_EXPECTEDCONST )
- '' error recovery: fake an expr
- astDelTree( expr )
- expr = astNewCONSTi( 0, FB_DATATYPE_INTEGER )
- end if
-
- '' follow the GCC 3.x ABI
- align = astGetValueAsInt( expr )
- astDelNode( expr )
- if( align < 0 ) then
- align = 0
- elseif( align > FB_INTEGERSIZE ) then
- align = 0
- elseif( align = 3 ) then
- align = 2
- end if
-
- else
- align = 0
- end if
+ '' [FIELD '=' ConstExpression]
+ dim as integer align = cFieldAlignmentAttribute( )
'' start a new compound, or any EXTERN..END EXTERN used around this struct
'' would turn-off function mangling depending on the mode passed
Code: Select all
Type SDS Field = 2 'short-dword-short
Union
Type
As UShort D_DH ''Most significant bit is to the 'right'
As UInteger D_C
As UShort D_DL
End Type
Type
As UInteger D_B
As UInteger D_A
End Type
End Union
Declare Property D_D as UInteger
Declare Property D_D( ByVal Input_ as UInteger )
End Type
Property SDS.D_D As UInteger
D_D = D_DL or D_DH shl 16
End Property
Property SDS.D_D( ByVal Input_ as UInteger )
D_DL = Input_ and &HFFFF
D_DH = Input_ Shl 16
End Property
Code: Select all
Union StringDescriptor
Dim As String S
Type
Dim As Zstring Ptr PointerToCharacter
Dim As Integer StringLength
Dim As Integer MemorySize
End Type
End Union
Why should it get allowed? (IMHO it's not useful.)fxm wrote:Why this is not allowed?
Don't focalized on my previous example which only describes the descriptor structure using an Union block.TJF wrote:Why should it get allowed? (IMHO it's not useful.)fxm wrote:Why this is not allowed?
Code: Select all
Union ReturnValue
Dim As String S
Dim As Integer I
Dim As Double D
End Union
Scope
Dim As ReturnValue rv
rv.S = "Hello!"
Print "'" & rv.S & "'", Len(rv.S)
rv.S = ""
End Scope
A workaround to use a string in an Union:fxm wrote:Don't focalized on my previous example which only describes the descriptor structure using an Union block.TJF wrote:Why should it get allowed? (IMHO it's not useful.)fxm wrote:Why this is not allowed?
Else, it can be used for returning different types of data in one structure.I know that Union does not support field with constructor/destructor (a string being a pseudo object).Code: Select all
Union ReturnValue Dim As String S Dim As Integer I Dim As Double D End Union Scope Dim As ReturnValue rv rv.S = "Hello!" Print "'" & rv.S & "'", Len(rv.S) rv.S = "" End Scope
But we could consider that object declared inside an Union is not automatically built or destroyed, but only from the user program to do so (the string descriptor might be just initialized with its 12 bytes to 0 as a numeric field).
Code: Select all
Union ReturnValue
Declare Property S () As String
Declare Property S (Byref value As String)
Dim As Integer I
Dim As Double D
Declare Destructor ()
Type
Private:
Dim As Byte StringDescriptor(0 To Sizeof(String) - 1)
End Type
End Union
Property ReturnValue.S () As String
Property = *Cast(String Ptr, @This.StringDescriptor(0))
End property
Property ReturnValue.S (Byref value As String)
*Cast(String Ptr, @This.StringDescriptor(0)) = value
End property
Destructor ReturnValue ()
This.S = ""
End Destructor
Scope
Dim As ReturnValue rv
rv.S = "Hello!"
Print "'" & rv.S & "'", Len(rv.S)
End Scope
Sleep
Code: Select all
Union ReturnValue
Declare Function S () Byref As String
Dim As Integer I
Dim As Double D
Declare Destructor ()
Type
Private:
Dim As Byte StringDescriptor(0 To Sizeof(String) - 1)
End Type
End Union
Function ReturnValue.S () Byref As String
Function = *Cast(String Ptr, @This.StringDescriptor(0))
End Function
Destructor ReturnValue ()
This.S = ""
End Destructor
Scope
Dim As ReturnValue rv
rv.s = "Hello!"
Print "'" & rv.s & "'", Len(rv.s)
End Scope
Sleep
Yeah, I updated my two workarounds!counting_pine wrote:To avoid making an assumption about the descriptor size, I suggest changing it to: 'Dim As Byte StringDescriptor(0 To sizeof(string)-1)'