Freebasic 1.20.0 Development

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

BUG #3 with new STRING*N

LSET and RSET overflow the fix-len string field by always writing a null ubyte just after the last character of the fix-len string.
I assume LSET and RSET have not been updated for the new STRING*N.
Example (result NOT OK):
  • Code: Select all

    Type UDT Field = 1
        Dim As String * 5 s1
        Dim As String * 5 s2
    End Type
    
    Dim As UDT u
    
    u.s2 = "  XYZ"
    Rset u.s1, "XYZ"
    Print "[" & u.s2 & "]", "[" & u.s1 & "]",
    If u.s2 = u.s1 Then Print "OK" Else Print "NOT OK"
    For I As Integer = 0 To Len(u.s1) - 1
        Print u.s2[I], u.s1[I]
    Next I
    Print
    
    u.s2 = "ABC  "
    Lset u.s1, "ABC"
    Print "[" & u.s2 & "]", "[" & u.s1 & "]",
    If u.s2 = u.s1 Then Print "OK" Else Print "NOT OK"
    For I As Integer = 0 To Len(u.s1) - 1
        Print u.s2[I], u.s1[I]
    Next I
    Print
    
    Sleep
    
    • Code: Select all

      [  XYZ]       [  XYZ]       NOT OK
      0             32
      32            32
      88            88
      89            89
      90            90
      
      [ BC  ]       [ABC  ]       NOT OK
      0             65
      66            66
      67            67
      32            32
      32            32
      

Note: There appears to be no problem with the MID (statement) instruction:
Mid( text , start [, length ] ) = expression
Example (result OK):
  • Code: Select all

    Type UDT Field = 1
        Dim As String * 5 s1
        Dim As String * 5 s2
    End Type
    
    Dim As UDT u
    
    u.s2 = "  123"
    u.s1 = "  1  "
    Mid(u.s1, 4) = Mid(u.s2, 4)
    Print "[" & u.s2 & "]", "[" & u.s1 & "]",
    If u.s2 = u.s1 Then Print "OK" Else Print "NOT OK"
    For I As Integer = 0 To Len(u.s1) - 1
        Print u.s2[I], u.s1[I]
    Next I
    Print
    
    Sleep
    
    • Code: Select all

      [  123]       [  123]       OK
      32            32
      32            32
      49            49
      50            50
      51            51
      

Comment: I think I have now finished all my tests for this new STRING*N.
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

Even I am still learning about some keyword behaviors:
For compatibility with QBasic, Lset can also copy a user defined type variable into another one. The copy is made byte for byte, without any care for fields or alignment. It's up to the programmer to take care for the validity of the result.
shadow008
Posts: 86
Joined: Nov 26, 2013 2:43

Re: Freebasic 1.20.0 Development

Post by shadow008 »

I have a small idea for a feature request:

Make procptr() capable of returning the implicit constructor/copy constructor/destructor functions. A call to procptr for a UDT's constructor (et. al.) would get either the explicit default constructor (if defined), or the implicit default one transparently.

The use case would be simplifying code paths when working in a type erased system. You either do the work of ensuring types that don't need them (blittable data) have explicit [con/de]structors, or you have two code paths for most things and choose between each for different types. Having a unified interface to a type's lifetime functions would entirely satisfy the first option without the boilerplate code. Thoughts?
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

There are cases where there are no constructors or copy-constructors or destructors (neither explicit nor implicit).
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Freebasic 1.20.0 Development

Post by coderJeff »

fxm wrote: Mar 20, 2024 19:21 BUG #3 with new STRING*N

LSET and RSET overflow the fix-len string field by always writing a null ubyte just after the last character of the fix-len string.
I assume LSET and RSET have not been updated for the new STRING*N.
Yes, not updated. I forget about these statements.

For interest, some things I learned:
- LSET/RSET have nearly the same implementation as written in 2005 and have logic already for padding with spaces. The logic to recognize the new string*n type is missing.
- I find this old note to myself regarding LSET/RSET from the time when 'extends (z|w)string' feature added:
'' !!!TODO!!! - if udt extends z|wstring, check if operator len()
'' was overloaded and pass the length parameters to a separate
'' rtlib function
- The LEFTSELF() string function was added to solve a specific performance issue within fbc itself for the '-gen c' backend' - it is not a fully realized feature addition. fbc-int/string.bi:fbc.LEFTSELF() was written as an optimization for var-len strings, and therefore is not well optimized for the string*n type. Even though the optimization for string*n is poor, string*n will still work ok with leftself due to copying string*n to a temporary descriptor and copying the result back to original string.
shadow008
Posts: 86
Joined: Nov 26, 2013 2:43

Re: Freebasic 1.20.0 Development

Post by shadow008 »

fxm wrote: Mar 22, 2024 6:12 There are cases where there are no constructors or copy-constructors or destructors (neither explicit nor implicit).
That matches my understanding but I will note such is not mentioned in the documentation: https://www.freebasic.net/wiki/ProPgCto ... MPCTORDTOR

Accounting for that, maybe a further change to have procptr behave more like a compile time constant as opposed to erroring at compile time if the procedure doesn't exist? It seems reasonable that it could return the same as it does now with an internal function ptr, or a null any ptr if the procedure doesn't exist.
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

Indeed, for very simple UDT with for example only numeric member fields without initializers:
- the compiler does not add an implicit constructor but only allocates memory set to 0,
- the compiler does not add an implicit copy-constructor but only performs a shallow (bitwise) copy,
- the compiler does not add an implicit destructor but only frees the memory.

The documentation does not go into these under-the-hood intricacies.
Is it necessary to detail all this in the documentation?
(maybe a simple note like above in the Programmer's Guide only?)
shadow008
Posts: 86
Joined: Nov 26, 2013 2:43

Re: Freebasic 1.20.0 Development

Post by shadow008 »

fxm wrote: Mar 22, 2024 16:54 Is it necessary to detail all this in the documentation?
(maybe a simple note like above in the Programmer's Guide only?)
I don't think it does after giving it some thought. The implicit lifetime functions aren't exposed to the user in any meaningful way right now, so it's not the user's business how things happen. It seems like more of a fun-fact in the current situation.
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Freebasic 1.20.0 Development

Post by coderJeff »

coderJeff wrote: Mar 15, 2024 12:40
fxm wrote: Mar 12, 2024 9:28 (to be removed in fbc version 1.20.0 ?)
Seems like something could be improved here and need to investigate what is going on in the rtlib:
- rtrim( string )
- rtrim( string, filter )
- rtrim( string, any filter )
The test-suite has some tests for [L|R]TRIM, however does not specifically test behaviours with CHR(0) either for the string argument or the filter argument. I think behaviour should be changed - however, there are several places internally where the rtlib uses common functions to scan a string for NUL or 32, so need to add some tests first for a starting point.

FYI, unrelated, when starting to write the tests, I see this:

Code: Select all

const s = chr( 32 ) '' allowed - this can be constant folded
const z = chr( 0 )  '' error - chr(0) can not be constant folded (due to fbc's internal representation)
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

coderJeff wrote: Mar 23, 2024 14:00 The test-suite has some tests for [L|R]TRIM, however does not specifically test behaviours with CHR(0) either for the string argument or the filter argument. I think behaviour should be changed - however, there are several places internally where the rtlib uses common functions to scan a string for NUL or 32, so need to add some tests first for a starting point.
Yes, now I only see this last behavior to study.
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

Jeff,

Back to : Pass Byref to a function, Return Byref from a function


Assignment of the 3 types of string ('String', 'String * N', 'Zstring * N+1') by calling 2 types of function ('Byref As String', 'Byref As Zstring'):
- either passing by reference to the function,
- or returning by reference from the function.

Example :

Code: Select all

#macro printStringUbytes(s)
    Print "[" & s & "](";
    For I As Integer = 0 To Len(s) - 1
        Print (s)[I];
        If I < Len(s) - 1 Then
            Print " ";
        End If
    Next I
    Print ")";
#endmacro

#macro printTestResult(s, s0)
    Print "   ";
    If s = s0 Then
        Print "OK"
    Else
        Print "NON OK,"
        Print "         could have been : ";
        printStringUbytes(s0)
        Print
    End If
#endmacro


Print "1. Pass/Return to/from a 'Byref As String' function :"

Function testByrefString(Byref s As String) Byref As String
    Print "  =>  ";
    s = "12 "
    Return s
End Function

Scope
    Dim As String s = "1    "
    Print "   1.1 String :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefString(s)
    printStringUbytes(s)
    printTestResult(s, "12 ")
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefString(s)) = "123 "
    printStringUbytes(s)
    printTestResult(s, "123 ")
End Scope

Scope
    Dim As String * 5 s = "1    "
    Print "   1.2 String * 5 :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefString(s)
    printStringUbytes(s)
    #if __FB_VERSION__ >= "1.20.0"
        printTestResult(s, "12   ")
    #else
        printTestResult(s, "12 ")
    #endif
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefString(s)) = "123 "
    printStringUbytes(s)
    #if __FB_VERSION__ >= "1.20.0"
        printTestResult(s, "123  ")
    #else
        printTestResult(s, "123 ")
    #endif
End Scope

Scope
    Dim As Zstring * 5+1 s = "1    "
    Print "   1.3 Zstring * 5+1 :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefString(s)
    printStringUbytes(s)
    printTestResult(s, "12 ")
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefString(s)) = "123 "
    printStringUbytes(s)
    printTestResult(s, "123 ")
End Scope

Print


Print "2. Pass/Return to/from a 'Byref As Zstring' function :"

Function testByrefZstring(Byref s As Zstring) Byref As Zstring
    Print "  =>  ";
    s = "12 "
    Return s
End Function

Scope
    Dim As String s = "1    "
    Print "   2.1 String :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefZstring(s)
    printStringUbytes(s)
    printTestResult(s, "12 ")
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefZstring(s)) = "123 "
    printStringUbytes(s)
    printTestResult(s, "123 ")
End Scope

Scope
    Dim As String * 5 s = "1    "
    Print "   2.2 String * 5 :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefZstring(s)
    printStringUbytes(s)
    #if __FB_VERSION__ >= "1.20.0"
        printTestResult(s, "12   ")
    #else
        printTestResult(s, "12 ")
    #endif
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefZstring(s)) = "123 "
    printStringUbytes(s)
    #if __FB_VERSION__ >= "1.20.0"
        printTestResult(s, "123  ")
    #else
        printTestResult(s, "123 ")
    #endif
End Scope

Scope
    Dim As Zstring * 5+1 s = "1    "
    Print "   2.3 Zstring * 5+1 :"
    Print "      pass   : ";
    printStringUbytes(s)
    testByrefZstring(s)
    printStringUbytes(s)
    printTestResult(s, "12 ")
    s = "1    "
    Print "      return : ";
    printStringUbytes(s)
    (testByrefZstring(s)) = "123 "
    printStringUbytes(s)
    printTestResult(s, "123 ")
End Scope

Sleep
  • - With fbc version 1.10.0:

    Code: Select all

    1. Pass/Return to/from a 'Byref As String' function :
       1.1 String :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [123 ](49 50 51 32)   OK
       1.2 String * 5 :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   NON OK,
             could have been : [123 ](49 50 51 32)
       1.3 Zstring * 5+1 :
          pass   : [1    ](49 32 32 32 32)  =>  [1    ](49 32 32 32 32)   NON OK,
             could have been : [12 ](49 50 32)
          return : [1    ](49 32 32 32 32)  =>  [1    ](49 32 32 32 32)   NON OK,
             could have been : [123 ](49 50 51 32)
    
    2. Pass/Return to/from a 'Byref As Zstring' function :
       2.1 String :
          pass   : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 0 32)   NON OK,
             could have been : [12 ](49 50 32)
          return : [1    ](49 32 32 32 32)  =>  [123  ](49 50 51 32 0)   NON OK,
             could have been : [123 ](49 50 51 32)
       2.2 String * 5 :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [123 ](49 50 51 32)   OK
       2.3 Zstring * 5+1 :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [123 ](49 50 51 32)   OK
    
    - With fbc version 1.20.0:

    Code: Select all

    1. Pass/Return to/from a 'Byref As String' function :
       1.1 String :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [123 ](49 50 51 32)   OK
       1.2 String * 5 :
          pass   : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 32 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 32 32)   NON OK,
             could have been : [123  ](49 50 51 32 32)
       1.3 Zstring * 5+1 :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   NON OK,
             could have been : [123 ](49 50 51 32)
    
    2. Pass/Return to/from a 'Byref As Zstring' function :
       2.1 String :
          pass   : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 0 32)   NON OK,
             could have been : [12 ](49 50 32)
          return : [1    ](49 32 32 32 32)  =>  [123  ](49 50 51 32 0)   NON OK,
             could have been : [123 ](49 50 51 32)
       2.2 String * 5 :
          pass   : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 0 32)   NON OK,
             could have been : [12   ](49 50 32 32 32)
          return : [1    ](49 32 32 32 32)  =>  [12   ](49 50 32 0 32)   NON OK,
             could have been : [123  ](49 50 51 32 32)
       2.3 Zstring * 5+1 :
          pass   : [1    ](49 32 32 32 32)  =>  [12 ](49 50 32)   OK
          return : [1    ](49 32 32 32 32)  =>  [123 ](49 50 51 32)   OK
    

For fbc version 1.20.0 only:
- Can you correct the cases '2.1 pass' and '2.2 pass' at least ?
(the '0' of the terminal character of zstring does not play its role of end)
- Could you correct other 'NON OK' cases ('return' cases) ?
- Note: Only the cases '1.1' and '1.2' are compatible with the use of Chr(0) by user, and the results are similar (only the case '1.2 return' fails).
Last edited by fxm on Mar 30, 2024 19:08, edited 3 times in total.
Reason: The 2 utility Sub's are transformed into macros and only the two main functions remain in the form of procedures (because, for a most reliable test possible of parameter passing, the verification part must not use any parameter passing).
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Freebasic 1.20.0 Development

Post by dodicat »

I tried to force a const chr(0).
Results:

Code: Select all

'#include "crt.bi"
const C=!"\0"
#print typeof(C)

Sub memcopy(dest As Any Ptr,src As Any Ptr,count As Long)
    Dim As Ubyte Ptr newdst=dest
    Dim As Ubyte Ptr newsrc=src
    While count
        count-=1 
        *newdst=*newsrc
        newdst+=1
        newsrc+=1
    Wend
End Sub
print "const C=!""\0"""
print asc(C),"asc(C)"
print len(C),"len(C)"
print "'";C;"'","actual C"
dim as string s="abc"+C+"def"
print s,"string s with C included (strange!)"
dim as ubyte u(0 to 6)={asc("a"),asc("b"),asc("c"),asc(C),asc("d"),asc("e"),asc("f")}
dim as string g=string(ubound(u)+1,0)
memcopy(@g[0],@u(0),len(g))
print g,"string g via memcopy  byte by byte from a ubyte array containing C"
print "show the string characrters g and original s"
print "          string g                    string s"
for n as long=0 to len(g)-1
    print g[n],chr(g[n]),s[n],chr(s[n])
    next
print *cast(zstring ptr,@u(0)),"cast the ubytes to zstring"

sleep 
Note: difference between 64 and 32 bit compilers (fbc 1.10.1)
Where can I get hold of the latest 1.20?
Thank you.
fxm
Moderator
Posts: 12132
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Freebasic 1.20.0 Development

Post by fxm »

St_W wrote: Dec 17, 2011 21:59 Automated recent git builds at:
https://users.freebasic-portal.de/stw/builds/
fbfans
Posts: 17
Joined: Nov 27, 2023 0:29

Re: Freebasic 1.20.0 Development

Post by fbfans »

dodicat wrote: Mar 26, 2024 10:59 I tried to force a const chr(0).
Results:

Code: Select all

'#include "crt.bi"
const C=!"\0"
#print typeof(C)

Sub memcopy(dest As Any Ptr,src As Any Ptr,count As Long)
    Dim As Ubyte Ptr newdst=dest
    Dim As Ubyte Ptr newsrc=src
    While count
        count-=1 
        *newdst=*newsrc
        newdst+=1
        newsrc+=1
    Wend
End Sub
print "const C=!""\0"""
print asc(C),"asc(C)"
print len(C),"len(C)"
print "'";C;"'","actual C"
dim as string s="abc"+C+"def"
print s,"string s with C included (strange!)"
dim as ubyte u(0 to 6)={asc("a"),asc("b"),asc("c"),asc(C),asc("d"),asc("e"),asc("f")}
dim as string g=string(ubound(u)+1,0)
memcopy(@g[0],@u(0),len(g))
print g,"string g via memcopy  byte by byte from a ubyte array containing C"
print "show the string characrters g and original s"
print "          string g                    string s"
for n as long=0 to len(g)-1
    print g[n],chr(g[n]),s[n],chr(s[n])
    next
print *cast(zstring ptr,@u(0)),"cast the ubytes to zstring"

sleep 
Note: difference between 64 and 32 bit compilers (fbc 1.10.1)
Where can I get hold of the latest 1.20?
Thank you.
const C=!"\0"
print "abc"+C+"def" 'isOK
print len("abc" + C + "def") 'IsOK
Dim As String s = "abc" + C + "def"
Print s 'Is Error
Print Len(s) 'isError
Sleep
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Freebasic 1.20.0 Development

Post by dodicat »

Thanks for the link fxm.
Post Reply